当前位置: 首页 > 知识库问答 >
问题:

从签名PDF中提取PKCS1

漆雕亮
2023-03-14

我必须从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()方法在验证它抛出的签名后异常转换器:java。安全SignatureException:未初始化用于签名的对象

共有2个答案

卫泉
2023-03-14

我已经审查了代码,似乎类PdfPKCS7不允许访问摘要。但是,内容被存储在私有成员PdfPKCS7.digest中。所以使用反射可以让你提取它。我在这里和这里发现了一个类似的例子(基本相同)

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。核实(摘要)

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

谢昊乾
2023-03-14

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

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

正如OP已经观察到的,PdfPKCS7。getEncodedPKCS7()失败,出现“ExceptionConverter:java.security.SignatureException:object not initialized for signing”。原因是此方法用于检索由PdfPKCS7实例新构造的签名容器。

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

AcroFields fields = reader.getAcroFields();
PdfDictionary sigDict = fields.getSignatureDictionary(name); 
PdfString contents = sigDict.getAsString(PdfName.CONTENTS);
byte[] contentBytes = contents.getOriginalBytes();

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

使用BouncyCastle分析此容器并不困难,但详细信息可能取决于您使用的确切BouncyCastle版本。

 类似资料:
  • 是否可以用开放源码软件库pdfbox提取已签名PDF的可见签名(图像)? 工作流: null 像下面这样的oop风格的东西会很棒: 找到了类PDSignature和如何签署一个PDF,但没有解决方案提取一个可见的签名作为图像。

  • 我用Adobe LiveCycle Designer创建了一个PDF表单。我现在正在努力从PDF中以编程方式提取填充后的数据。 我尝试使用poppler(qt4绑定,但我想这并不重要),但显然poppler无法处理XFA表单。虽然evince和okular能够显示表单。。。 据我所知,PDF包含一个XDP,而XDP又包含XFA表单。我的问题是,我如何从PDF中提取这些数据?

  • 我有一个场景,我需要用iText7库从pdf中获取签名信息。签名可能存在,也可能不存在。当我为没有任何数字签名的PDF实例化一个新的对象时,会出现异常 “没有相关的PdfWriter用于进行间接操作。” .如果有签名,就很好用。我不确定如何纠正这个异常。 更新为包含代码示例

  • 我想知道我们如何使用ITEXT7来提取与数字签名相关的图像信息。我知道过去也有人问过类似的问题,但它们大多是围绕ITEXT5提出的,在对软件进行了所有更新和修改后,这与ITEXT7大不相同。

  • 假设我的用户去了他们办公室的扫描仪。扫描仪能够生成扫描文档的PDF。这基本上就是我拥有的文件类型。 我想做的是从这个PDF中提取文本。这不是“第一代”pdf,因为文本没有嵌入到pdf中。文本嵌入在PDF中的图像中。 PDFBox的iText中是否有允许检索此数据的功能?如果可能的话,我正在尝试避免对图像进行OCR。我希望IText或PDFBox中有一些内置的东西可以做到这一点。 请注意,我不是在谈

  • 我知道以前也有人问过类似的问题,但是这些问题已经过时了(有些问题可以追溯到2006年)。 我有一个. net 3.5应用程序(w/iTextSharp 5),我正在转换为. net核心(iText 7),它从联邦快递跟踪文档中提取签名,通过SOAP服务以字节[]数组发送。这段代码多年来一直运行良好,只是略有更新。从联邦快递返回的PDF文档中有几个图像,但签名块不是110x46图像(这是pdf文件中