我是使用数字签名的新手。在其中一个项目中,我们使用 Apache PdfBox 来处理数字签名的 pdf 文件。虽然我们可以测试所有功能,但签名 pdf 文件的验证是我们无法破解的。我们使用 BouncyCastle 作为提供者。下面是代码:
从 pdf 文件中获取数字签名和签名内容:
byte[] signatureAsBytes = pdsignature.getContents(new FileInputStream(this.INPUT_FILE));
byte[] signedContentAsBytes = pdsignature.getSignedContent(new FileInputStream(this.INPUT_FILE));
数字签名验证:
Security.addProvider(new BouncyCastleProvider());
Signature signer = Signature.getInstance("RSA","BC");
//Get PublicKey from p7b file
X509Certificate cert509=null;
File file = new File("C:\\certificate_file.p7b");
FileInputStream fis = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection c = cf.generateCertificates(fis);
Iterator it = c.iterator();
PublicKey pubkey;
while (it.hasNext())
{
cert509 = (X509Certificate) it.next();
pubkey = cert509.getPublicKey();
}
boolean VERIFIED=false;
Security.addProvider(new BouncyCastleProvider());
Signature signer = Signature.getInstance("RSA","BC");
PublicKey key=this.getPublicKey(false);
signer.initVerify(key);
List<PDSignature> allsigs = this.PDFDOC.getSignatureDictionaries();
Iterator<PDSignature> i = allsigs.iterator();
while(i.hasNext())
{
PDSignature sig = (PDSignature) i.next();
byte[] signatureAsBytes = sig.getContents(new FileInputStream(this.INPUT_FILE));
byte[] signedContentAsBytes = sig.getSignedContent(new FileInputStream(this.INPUT_FILE));
signer.update(signedContentAsBytes);
VERIFIED=signer.verify(signatureAsBytes);
}
System.out.println("Verified="+VERIFIED);
以下是 p7b 格式的证书的相关摘录 - 我使用 BouncyCastle 作为安全提供程序:
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
Key: Sun RSA public key, 2048 bits
Validity: [From: Tue Aug 06 12:26:47 IST 2013,
To: Wed Aug 05 12:26:47 IST 2015]
Algorithm: [SHA256withRSA]
使用上面的代码我总是得到“false”的响应。我不知道如何解决这个问题。请帮忙
您的主要问题是,有多种类型的 PDF 签名,其签名容器的格式以及实际签名字节的不同。另一方面,您的 BC 代码只能验证上述签名容器中包含的裸签名字节序列。
可互操作的签名类型
正如标题已经说明的那样,以下列表包含或多或少严格定义的“可互操作的签名类型”。这PDF规格 http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf指定一种还包含完全自定义签名方案的方法。但让我们假设我们处于可互操作的情况。签名类型的集合被简化为:
-
adbe.x509.rsa_sha1定义于ISO 32000-1 http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf第12.8.3.2节PKCS#1 签名;签名值Contents包含一个DER 编码的 PKCS#1 二进制数据对象;这个数据对象是一个相当裸露的签名,在 RSA 的情况下,是一个包含填充文档哈希和哈希算法的加密结构。
-
adbe.pkcs7.sha1定义于ISO 32000-1 http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf第12.8.3.3节PKCS#7 签名;签名值Contents包含一个DER 编码的 PKCS#7 二进制数据对象;该数据对象是一个大容器对象,它还可以包含元信息,例如它可能包含用于构建证书链的证书、用于证书吊销检查的吊销信息、用于修复签名时间的数字时间戳……文档字节范围的 SHA1 摘要应封装在 PKCS#7 SignedData 字段中,且 ContentInfo 类型为 Data。该 SignedData 的摘要应作为正常的 PKCS#7 摘要合并。
-
adbe.pkcs7.detached定义于ISO 32000-1 http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf第12.8.3.3节PKCS#7 签名;签名值Contents包含一个DER 编码的 PKCS#7 二进制数据对象, 往上看。文档字节范围内的原始签名消息摘要应作为正常的 PKCS#7 SignedData 字段合并。 PKCS#7 SignedData 字段中不得封装任何数据。
-
ETSI.CADES.分离定义于欧洲电信标准协会 TS 102 778-3 http://www.etsi.org/deliver/etsi_ts/102700_102799/10277803/01.02.01_60/ts_10277803v010201p.pdf并将融入 ISO 32000-2;签名值Contents包含一个CMS 中指定的 DER 编码 SignedData 对象; CMS 签名容器与 PKCS#7 签名容器关系密切,请参见上文。这本质上是 adbe.pkcs7.detached 的不同配置和更严格定义的变体。
-
欧洲电信标准协会RFC3161定义于欧洲电信标准协会 TS 102 778-4 http://www.etsi.org/deliver/etsi_ts/102700_102799/10277804/01.01.02_60/ts_10277804v010102p.pdf并将融入 ISO 32000-2;签名值Contents包含一个RFC 3161 中指定的 TimeStampToken;时间戳令牌再次与 PKCS#7 签名容器密切相关,请参见上文,但它们包含特殊的数据子结构,其中包含文档哈希、时间戳创建时间以及发布时间服务器上的信息。
我建议研究我指定的规范以及其中引用的文档,主要是 RFC。基于这些知识,您可以轻松找到合适的 BouncyCastle 类来分析不同的签名Contents.
PS(2021):同时 ISO 32000-2 已发布,并且确实包含以下规范ETSI.CADES.分离 and 欧洲电信标准协会RFC3161。 PAdES 的 ETSI 技术规范 TS 102 778-* 已被实际规范 ETSI EN 319 142-* 取代。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)