2016-11-13 12 views
0

我試圖在Android上使用iText簽署PDF文檔。證書已包含並在模擬器中激活。下面是我使用的庫:在Android上使用Spongycastle和iText獲取NoSuchMethodError

compile 'com.android.support:appcompat-v7:23.2.0' 
compile 'com.itextpdf:itextg:5.5.9' 
testCompile 'junit:junit:4.12' 
compile files('libs/itext-licensekey-1.0.4.jar') 

compile 'com.madgag.spongycastle:core:1.54.0.0' 
compile 'com.madgag.spongycastle:prov:1.54.0.0' 
compile 'com.madgag.spongycastle:pkix:1.54.0.0' 
compile 'com.madgag.spongycastle:pg:1.54.0.0' 

下面是我用來簽署現有的PDF文檔類:

public class SignPDF { 

static { 
    Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1); 
} 

public void sign(String src, String dest, 
       Certificate[] chain, PrivateKey pk, String digestAlgorithm, String provider, 
       MakeSignature.CryptoStandard subfilter, String reason, String location) 
     throws GeneralSecurityException, IOException, DocumentException { 

    PdfReader reader = new PdfReader(src); 
    FileOutputStream os = new FileOutputStream(dest); 
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0'); 

    PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); 
    appearance.setReason(reason); 
    appearance.setLocation(location); 
    appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig"); 

    ExternalDigest digest = new BouncyCastleDigest(); 
    ExternalSignature signature = 
      new PrivateKeySignature(pk, digestAlgorithm, provider); 
    MakeSignature.signDetached(appearance, digest, signature, chain, 
      null, null, null, 0, subfilter); 
} 

private static String[] PERMISSIONS_STORAGE = { 
     Manifest.permission.READ_EXTERNAL_STORAGE, 
     Manifest.permission.WRITE_EXTERNAL_STORAGE}; 
private static final int REQUEST_EXTERNAL_STORAGE = 1; 
public static final String SRC = Environment.getExternalStorageDirectory() + File.separator + "testdsign_1.pdf"; // consider the file to be created earlier 
public static final String DEST = Environment.getExternalStorageDirectory() + File.separator + "testdsign_2.pdf"; 

public static void signat(Activity a) 
     throws IOException, GeneralSecurityException { 

    int permission = ActivityCompat.checkSelfPermission(a, Manifest.permission.WRITE_EXTERNAL_STORAGE); 

    if (permission != PackageManager.PERMISSION_GRANTED) { 
     // We don't have permission so prompt the user 
     ActivityCompat.requestPermissions(
       a, 
       PERMISSIONS_STORAGE, 
       REQUEST_EXTERNAL_STORAGE 
     ); 
    } 
    String path = Environment.getExternalStorageDirectory() + File.separator + "keystore.p12"; 
    char[] pass = "123456".toCharArray(); 
    BouncyCastleProvider provider = new BouncyCastleProvider(); 
    Security.addProvider(provider); 
    KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName()); 
    ks.load(new FileInputStream(path), pass); 
    String alias = (String) ks.aliases().nextElement(); 
    PrivateKey pk = (PrivateKey) ks.getKey(alias, pass); 
    Certificate[] chain = ks.getCertificateChain(alias); 
    SignPDF app = new SignPDF(); 
    try { 
     app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, provider.getName(), 
       MakeSignature.CryptoStandard.CMS, "Test", "Ghent"); 
    } catch (DocumentException e) { 

     e.printStackTrace(); 
    } 
} 

}

最後,錯誤堆棧

java.lang.NoSuchMethodError: No direct method <init>(I)V in class Lorg/spongycastle/asn1/ASN1Integer; or its super classes (declaration of 'org.spongycastle.asn1.ASN1Integer' appears in /data/data/dsign.example.com.dsigntest/files/instant-run/dex/slice-core-1.54.0.0_016eb8590d95a10a91a6367c6ca7de97121683a4-classes.dex) 
                      at com.itextpdf.text.pdf.security.PdfPKCS7.getEncodedPKCS7(PdfPKCS7.java:826) 
                      at com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:154) 
                      at dsign.example.com.dsigntest.SignPDF.sign(SignPDF.java:56) 
                      at dsign.example.com.dsigntest.SignPDF.signat(SignPDF.java:91) 
                      at dsign.example.com.dsigntest.MainActivity.onCreate(MainActivity.java:59) 
                      at android.app.Activity.performCreate(Activity.java:6237) 
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                      at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

問題的原因是什麼?感謝您的幫助。

+1

查看itextg在其pom.xml中所需的SC版本。它當然不是1.54。 – mkl

+0

@AmedeeVanGasse謝謝,我會嘗試更改版本 – BekaBot

+0

@AmedeeVanGasse它的工作原理,我使用SC版本1.47 [This](http://grepcode.com/snapshot/repo1.maven.org/maven2/com.madgag /scprov-jdk15on/1.47.0.1/)鏈接。請將您的評論複製爲下面的內容,以便我可以接受。謝謝。 – BekaBot

回答

4

您正在使用BouncyCastle版本1.54。 iTextG 5.5。*需要SpongyCastle版本1.47.0.2(同時iText 5.5。*需要BouncyCastle版本1.49)。

推薦的方法是將iTextG添加到Maven/Gradle/... config作爲依賴項,並且您的構建工具將自動提取正確版本的SpongyCastle,該版本當前爲1.47.0.2。沒有必要手動尋找依賴關係。依賴關係解決方案是Android上解決的問題。

編輯:

有些人顯然不Maven構建工具(或搖籃),但手動搜索罐子上http://search.maven.org。如果你這樣做,而你盲目地搜索「海綿城堡」,那麼你只會發現錯誤版本。

正如人們可以在iTextG pom.xml看到:

<dependencies> 
    <dependency> 
    <groupId>com.madgag</groupId> 
    <artifactId>scprov-jdk15on</artifactId> 
    <version>1.47.0.2</version> 
    <optional>true</optional> 
    </dependency> 
    <dependency> 
    <groupId>com.madgag</groupId> 
    <artifactId>scpkix-jdk15on</artifactId> 
    <version>1.47.0.2</version> 
    <optional>true</optional> 
    </dependency> 
    ... 
</dependencies> 

我再說一遍,這些都是iText的5.5正確的依賴*:

  • 的groupId:com.madgag
  • 的artifactId:scprov-jdk15onscpkix-jdk15on
  • 版本:1.47.0.2

這些依賴WRONG爲iText的5.5 *:

  • 的groupId:com.madgag.spongycastle
  • 的artifactId:provpkix
  • 版本:[1.50,)

如果在確定您使用正確版本的SpongyCastle後仍然有問題,那麼您必須提出一個新問題。在你的問題,包括以下信息:

  • 你iTextG版本
  • 你SpongyCastle版本
  • 你的POM文件或搖籃文件,你得到錯誤的
  • 輸出的 mvn dependency:tree -Dverbose
  • 複製/粘貼。
+0

我仍然面臨同樣的問題,我正在使用itextg v5.5.10。 maven中的min spongycastle版本是1.50.0,有什麼想法? – leobelizquierdo

+2

您正在查看錯版Spongy Castle。從'1.50'開始,他們將'groupId'重命名爲'com.madgag.spongycastle'。對於'1.47.02',你可以在iTextG'pom.xml'中清楚地看到,'groupId'是'com.madgag',工件是'scprov-jdk15on'和'scpkix-jdk15on'。我再次檢查,我目前有我的瀏覽器打開http://search.maven.org,我可以找到工件。如果您仍然有問題,請發起一個新問題。 –

+0

謝謝!你拯救了我的一天。出於某種原因,來自jcenter或maven的當前版本的itextg沒有添加到pom的相關性。我瘋了。將這些com.madgag添加到我的gradle項目依賴關係中的確有竅門。 – giroxiii