2014-03-24 123 views
1

我想用iText對PDF文檔進行數字簽名。由於我將使用硬件加密器和JCE提供者,我最終還試圖在我的單元測試中測試擺脫BountyCastle,並暫時使用默認的SUN實現(直到硬件加密器到達)。MakeSignature.signDetached拋出沒有這樣的算法異常(SUN provider&SHA-256)

不過,我得到以下異常,當我運行我的程序:在線程「主要」 java.security.NoSuchAlgorithmException

例外:沒有這樣的算法:SHA256的提供商SUN 在sun.security.jca.GetInstance .getService(GetInstance.java:87) at java.security.MessageDigest上的java.security.Security.getImpl(Security.java:698) sun.security.jca.GetInstance.getInstance(GetInstance.java:206) .getInstance(MessageDigest.java:215) at com.itextpdf.text.pdf.security.DigestAlgorithms.getMessageDigest(DigestAlgorithms.java:159) at com.itextpdf.text.pdf.security.Provide rDigest.getMessageDigest(ProviderDigest.java:61) at SignDoc.signPdf(SignDoc.java:142) at SignDoc.main(com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:130) SignDoc.java:182)

碼的最後幾行情況如下:

//ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC"); 
    //ExternalDigest digest = new BouncyCastleDigest(); 
    //ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "SUN"); 
    ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "SunRsaSign"); 
    ExternalDigest digest = new ProviderDigest("SUN"); 
    MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS); 

正如你所看到的,我只是複製樣品,改變提供者的名稱和電話「新BouncyCastleDigest( )'to'new ProviderDigest(「SUN」)'

偷看iText的源代碼(5.5.1-SNAP SHOT),我發現了以下代碼片段可疑:

  1. MakeSignature.java線142 - 145

    的HashAlgorithm = externalSignature.getHashAlgorithm()被調用,然後在

    DigestAlgorithms使用。摘要(data,externalDigest.getMessageDigest(hashAlgorithm));

  2. PrivateKeySignature.java線76

    由於我使用的PrivateKeySignature,我偷看PrivateKeySignature.java,發現它返回它的私有類成員和的HashAlgorithm這是如何獲得建設中的值(線76) :

    這個。 hashAlgorithm = DigestAlgorithms.getDigest(DigestAlgorithms.getAllowedDigests(hashAlgorithm));

  3. DigestAlgorithms.java方法getAllowedDigests()和getDigest()

    反過來,getAllowedDigests()如果算法名在allowedDigests哈希映射(2.16.840.1.101.3發現返回了該算法的OID。 4.2.1在我的情況),否則它返回null。

    getDigest使用digestNames哈希映射從OID獲取摘要名稱。

    但是,對應於OID的digestNames散列映射中的名稱是SHA256,而不是SHA-256。

結果,最終消化名字得到的是「SHA256」,而不是「SHA256」和「SHA256」是導致Sun提供的NoSuchAlgorithm例外。

(我試圖讓直接使用Sun提供的消息摘要的實例,它成功地爲SHA256,但拋出同樣的異常,我彙報這裏SHA256。

這是使用JCE供應商時iText的問題?比BC其他

感激,如果任何人都可以對我的問題提供一些線索

+0

JCE確實沒有將「SHA256」定義爲SHA-256的別名。你能修改iText的digestNames哈希映射,並用2.16.840.1.101.3.4.2.1-> SHA-256替換2.16.840.1.101.3.4.2.1-> SHA256條目嗎? –

+0

感謝您的建議。我認爲這會解決我的問題,但我不確定這是否是正確的方法。無論如何,我會先試一試。 –

+0

如果我按照建議修改映射,則可以成功傳遞MessageDigest.getInstance。但是,當涉及到Signature.getInstance()時,我立即遇到了「沒有這樣的算法」異常(這一次它是期望SHA256withRSA的SHA-256withRSA,我相信)。看起來假設用於摘要的相同算法名稱(例如SHA-256)可以用作簽名算法的前綴是有問題的,因爲算法名稱在提供者(例如SHA256 vs SHA-256)中不一致, 。 –

回答

0

作爲暫時的解決辦法,我增加了以下內容以便PrivateKeySignature.java:

//臨時的解決辦法 - 到REM hashAlgorithm名稱中的連字符連接 // String signMode = hashAlgorithm +「with」+ encryptionAlgorithm; String signMode = hashAlgorithm.replaceAll(「 - 」,「」)+「with」+ encryptionAlgorithm; //結束臨時修復

至少現在它適用於我。我相信,必須研究如何在不同背景下使用不同算法的標準名稱,然後才能設計出長期解決方案。