java - 从签名 PDF 中提取 PKCS1

标签 java pdf itext digital-signature

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

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 字节数组来创建的。该文件看起来已由外部工具正确签名和验证。

// 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 notinitialed for签名

最佳答案

我已经查看了code并且似乎类 PdfPKCS7 不允许访问摘要。但是,内容存储在私有(private)成员 PdfPKCS7.digest 中。因此,使用反射将允许您提取它。 我发现了一个类似的例子herehere (基本相同)

PdfPKCS7 pdfPkcs7 = acroFields.verifySignature(name);
pdfPkcs7.verify();

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

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

 public byte[] getEncodedPKCS1() {
   try {
        if (externalDigest != null)
            digest = externalDigest;
        else
            digest = sig.sign();

     //skipped content

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

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

关于java - 从签名 PDF 中提取 PKCS1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38627375/

相关文章:

java - 如何在 spring mvc 中的服务器端验证上显示错误消息

javascript - Amcharts 中的乱码文本导出为 PDF

java - 如何以字符串 Base64 格式存储 PDF 内容

java - 如何解决 pdf header signature not found 错误?

java - 如何使用iText和Java选中具有相同变量名的PDF文件中的复选框

java - Hadoop上下文中Java的内存问题

java.io.FileNotFoundException : in. txt,(系统找不到指定的文件)

google-chrome - google chrome headless browser 能否用于向最终用户提供 PDF

ruby-on-rails - PDFkit 在生成带有图像的 pdf 时挂起

java - java中的正则表达式用于密码验证