首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从签名的PDF中提取PKCS1

从签名的PDF中提取PKCS1
EN

Stack Overflow用户
提问于 2016-07-28 04:55:53
回答 2查看 2.6K关注 0票数 3

我必须从PDF签名文档中提取签名字段,以创建打印的签名版本。到目前为止,我还能够使用以下iText代码恢复签名者证书、原因、签名日期和其他字段:

代码语言:javascript
复制
PdfReader reader = new PdfReader(signedPdf);
AcroFields af = reader.getAcroFields();
ArrayList<String> names = af.getSignatureNames();

SimpleDateFormat sdf = new SimpleDateFormat(
                    "dd/MM/yyyy 'a las' HH:mm:ss");

for (int i = 0; i < names.size(); ++i) {

    StringBuilder sb = new StringBuilder();
    String name = names.get(i);
    PdfPKCS7 pk = af.verifySignature(name);

    String firmante = CertificateInfo.getSubjectFields(
            pk.getSigningCertificate()).getField("CN");
    sb.append("Nombre del firmante: " + firmante + "\n");

    Date signDate = pk.getSignDate().getTime();
    String sdate = sdf.format(signDate);
    sb.append("Fecha y hora de la firma: " + sdate + "\n");


    String razon = pk.getReason();
    sb.append("proposito: " + razon + "\n");
}

据我所知,PDF签名是使用iText PdfPkcs7类创建的,使用setExternalDigest方法添加在外部应用程序中创建的PKCS1字节数组。该文件看起来正确签名,并由外部工具验证。

代码语言:javascript
复制
// Create the signature
PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA1", "BC", null, false);

//pkcs1Bytes is a byte array with the signed document hash
sgn.setExternalDigest(pkcs1Bytes, null, "RSA");

但是,打印版本所需的字段之一是“签名数字邮票”,它是签名文档散列或PKCS1的基本64字符串。

从已签名的PDF文档中提取PKCS1字节是可能的吗?

编辑:我忘记提到当我在验证签名后使用PdfPKCS7.getEncodedPKCS1()方法时,它会抛出ExceptionConverter: java.security.SignatureException: object not initialized for signing

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-29 07:18:10

我已经复习了代码,似乎类PdfPKCS7不允许访问摘要。但是,内容存储在私有成员PdfPKCS7.digest中。因此,使用反射将允许您提取它。我发现了一个类似的例子这里这里 (基本上是一样的)

代码语言:javascript
复制
PdfPKCS7 pdfPkcs7 = acroFields.verifySignature(name);
pdfPkcs7.verify();

Field digestField = PdfPKCS7.class.getDeclaredField("digest");
digestField.setAccessible(true);
byte[] digest = (byte[]) digestField.get(pdfPkcs7);

我认为您需要的变量是digest,因为在执行签名时该值是在getEncodedPKCS1中赋值的。

代码语言:javascript
复制
 public byte[] getEncodedPKCS1() {
   try {
        if (externalDigest != null)
            digest = externalDigest;
        else
            digest = sig.sign();

     //skipped content

并以下列方式在verify()中使用verifyResult = sig.verify(digest);

请注意,digest是一个私有变量,因此名称或内容可能取决于版本。检查特定版本的代码。

票数 3
EN

Stack Overflow用户

发布于 2016-07-29 07:43:28

考虑到您的代码,我假设您使用的是5.x iText版本,而不是7.x版本。

您可以使用反射(cf )。这个古老的答案或pedrofb的答案),或者您可以使用iText提取CMS签名容器,然后使用BouncyCastle分析该容器;如果使用iText的签名相关功能,BC的一个版本通常已经存在。

正如OP已经观察到的那样,PdfPKCS7.getEncodedPKCS7()在"ExceptionConverter: java.security.SignatureException: object未为签名而初始化“中失败。原因是此方法用于检索签名容器新构造的实例。

要使用iText提取CMS签名容器,可以使用以下代码:

代码语言:javascript
复制
AcroFields fields = reader.getAcroFields();
PdfDictionary sigDict = fields.getSignatureDictionary(name); 
PdfString contents = sigDict.getAsString(PdfName.CONTENTS);
byte[] contentBytes = contents.getOriginalBytes();

contentBytes现在包含编码的CMS容器(加上一些尾随字节,通常为空字节,因为内容值通常比签名容器所需的要大)。

使用BouncyCastle分析这个容器并不困难,但细节可能取决于您使用的确切BouncyCastle版本。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38627375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档