我收到错误“当签名应用于使用itext的pdf时,文档已被更改或损坏,因为签名已被应用。”
生成数字签名的pdf但绿色复选标记未到来。要获得绿色复选标记,必须采取哪些措施。
现在它说签名是无效的。
我使用以下链接作为参考 http://itextpdf.com/examples/iia.php?id=222
我使用以下代码使用iText应用签名。
String path = "resources/examplestore";
String keystore_password = "password";
String key_password = "password";
String alias = "signFiles";
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(path), keystore_password.toCharArray());
PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
String path = "resources/examplestore";
String keystore_password = "password";
String key_password = "password";
String alias = "signFiles";
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(path), keystore_password.toCharArray());
PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
PdfSignatureAppearance appearance = stamper
.getSignatureAppearance();
appearance.setReason("I'm approving this.");
appearance.setLocation("Foobar");
appearance.setVisibleSignature(new Rectangle(160, 732, 232, 780), 1, "second");
ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
I also Verify the code after this.
答案 0 :(得分:1)
我在这个答案中并不完全确定,因为我几乎不需要处理DSA签名,通常我必须处理RSA或ECDSA签名。
在看到“自签名被应用以来文档已被更改或损坏”消息时的第一个假设是实际文档散列与签名中包含的文档散列不同。 (更改文档会产生这样的差异。)但是,对于文档,签名的签名属性messageDigest
中的HASH值是正确的。
一个非常明显的特点是使用的签名算法:
1071 06 7: OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
: (ANSI X9.57 algorithm)
<05 00>
1080 05 0: NULL
: }
这是特殊的,因为签名算法需要包括HASH算法以允许验证,例如,
The algorithm identifier for DSA with SHA-1 signature values is:
id-dsa-with-sha1 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
us(840) x9-57 (10040) x9cm(4) 3 }
或
When SHA-224 is used, the OID is:
id-dsa-with-sha224 OBJECT IDENTIFIER ::= { joint-iso-ccitt(2)
country(16) us(840) organization(1) gov(101) csor(3)
algorithms(4) id-dsa-with-sha2(3) 1 }.
When SHA-256 is used, the OID is:
id-dsa-with-sha256 OBJECT IDENTIFIER ::= { joint-iso-ccitt(2)
country(16) us(840) organization(1) gov(101) csor(3)
algorithms(4) id-dsa-with-sha2(3) 2 }.
在旧的SMIME规范中,使用id-dsa而不是id-dsa-with-XXX被解释为id-dsa-with-sha1。
因此,如果在验证期间,您的签名中的算法标识符完全被接受,则它被解释为已在SHA1的上下文中使用;但是,您的代码(我假设签名first
和second
的签名代码在这方面是一致的),包含:
ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
即。你的代码哈希使用SHA-256。因此,您的签名将无法得到正面验证。
背景问题是,DSA签名的com.itextpdf.text.pdf.security.PdfPKCS7.setExternalDigest(byte[], byte[], String)
仅在digestEncryptionAlgorithmOid
中存储id-dsa OID,PdfPKCS7.getEncodedPKCS7(byte[], Calendar, TSAClient, byte[], Collection<byte[]>, CryptoStandard)
使用digestEncryptionAlgorithmOid
作为签名算法OID。
因此,对于所有DSA签名,id-dsa用作签名算法,即使它实际上根本不应该使用,如果使用它意味着SHA-1。
PS:在签名算法中不包括HASH算法的RSA签名的情况下,值没有问题,因为RSA签名实际上是提到所使用的HASH算法的编码结构。另一方面,DSA不是关于解码而是关于检查,所以没有任何隐含的HASH算法。