无法使用Apache PDFBOX验证数字签名 [英] Unable to verify digital signature using Apache PDFBOX

查看:131
本文介绍了无法使用Apache PDFBOX验证数字签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是使用数字签名的新手.在其中一个项目中,我们使用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规范指定了一种方法还包括完全自定义的签名方案.但是,让我们假设我们处于一种可互操作的情况.签名类型的集合可以归结为:

  • adbe.x509.rsa_sha1

    ETSI.CAdES.detached "rel ="noreferrer"> ETSI TS 102 778-3 ,并将集成到ISO 32000-2中;签名值 Contents 包含CMS中指定的 DER编码的SignedData对象; CMS签名容器与PKCS#7签名容器是近亲,请参见上文.从本质上讲,这是adbe.pkcs7.detached的轮廓不同且定义更严格的变体. 在

    ETSI.RFC3161 ="noreferrer"> ETSI TS 102 778-4 ,并将集成到ISO 32000-2中;签名值 Contents 包含RFC 3161中指定的 TimeStampToken ;时间戳记令牌再次与PKCS#7签名容器紧密相关,请参见上文,但是它们包含一个特殊的数据子结构,其中包含文档哈希,戳记创建的时间以及发布时间服务器上的信息.

我建议研究我命名的规范以及从中引用的文档,主要是RFC.基于这些知识,您可以轻松找到合适的BouncyCastle类来分析不同的签名 Contents .

I am a newbie in using Digital Signatures. In one of the projects we are using Apache PdfBox for processing digitally signed pdf files. While we could test all features, verification of signed pdf files is something we are unable to crack. We are using BouncyCastle as the provider. Below is the code:

//Get Digital Signature and Signed Content from pdf file

byte[] signatureAsBytes = pdsignature.getContents(new FileInputStream(this.INPUT_FILE));
byte[] signedContentAsBytes = pdsignature.getSignedContent(new FileInputStream(this.INPUT_FILE));

//Digital Signature Verification

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);

Below are relevant extracts from the certificate in p7b format - I am using BouncyCastle as security provider:

  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]

With the above code I am always getting response as "false". I have no idea how to fix the issue. Please help

解决方案

Your prime problem is that there are multiple types of PDF signatures differing in the format of the signature container and in what actually are the signed bytes. Your BC code, on the other hand, can verify merely naked signature byte sequences which are contained in the afore-mentioned signature containers.

Interoperable signature types

As the header already says, the following list contains "interoperable signature types" which are more or less strictly defined. The PDF specification specifies a way to also include completely custom signing schemes. But let us assume we are in an interoperable situation. The the collection of signature types burns down to:

  • adbe.x509.rsa_sha1 defined in ISO 32000-1 section 12.8.3.2 PKCS#1 Signatures; the signature value Contents contain a DER-encoded PKCS#1 binary data object; this data object is a fairly naked signature, in case of RSA an encrypted structure containing the padded document hash and the hash algorithm.

  • adbe.pkcs7.sha1 defined in ISO 32000-1 section 12.8.3.3 PKCS#7 Signatures; the signature value Contents contain a DER-encoded PKCS#7 binary data object; this data object is a big container object which can also contain meta-information, e.g. it may contain certificates for building certificate chains, revocation information for certificate revocation checks, digital time stamps to fix the signing time, ... The SHA1 digest of the document’s byte range shall be encapsulated in the PKCS#7 SignedData field with ContentInfo of type Data. The digest of that SignedData shall be incorporated as the normal PKCS#7 digest.

  • adbe.pkcs7.detached defined in ISO 32000-1 section 12.8.3.3 PKCS#7 Signatures; the signature value Contents contain a DER-encoded PKCS#7 binary data object, see above. The original signed message digest over the document’s byte range shall be incorporated as the normal PKCS#7 SignedData field. No data shall be encapsulated in the PKCS#7 SignedData field.

  • ETSI.CAdES.detached defined in ETSI TS 102 778-3 and will become integrated in ISO 32000-2; the signature value Contents contain a DER-encoded SignedData object as specified in CMS; CMS signature containers are close relatives to PKCS#7 signature containers, see above. This essentially is a differently profiled and stricter defined variant of adbe.pkcs7.detached.

  • ETSI.RFC3161 defined in ETSI TS 102 778-4 and will become integrated in ISO 32000-2; the signature value Contents contain a TimeStampToken as specified in RFC 3161; time stamp tokens again are a close relative to PKCS#7 signature containers, see above, but they contain a special data sub-structure harboring the document hash, the time of the stamp creation, and information on the issuing time server.

I would propose studying the specifications I named and the documents referenced from there, mostly RFCs. Based on that knowledge you can easily find the appropriate BouncyCastle classes to analyze the different signature Contents.

这篇关于无法使用Apache PDFBOX验证数字签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆