使用iTextSharp库提取pdf文件中包含的签名图像

时间:2013-06-28 15:52:31

标签: c# pdf itextsharp digital-signature

我有一个签名的PDF文件。有了这个使用iTextSharp库的功能,我找到了证书p7m签名:

        private void GetSignature(string FileName)
    {
        AcroFields acroFields = new PdfReader(FileName).AcroFields;
        List<string> names = acroFields.GetSignatureNames();

        foreach (var name in names)
        {
            PdfDictionary dict = acroFields.GetSignatureDictionary(name);
            PdfString contents = (PdfString)PdfReader.GetPdfObject(dict.Get(PdfName.CONTENTS));

            byte[] PKCS7 = contents.GetOriginalBytes();
            ByteArrayToFile(@"c:\signature\" + name + ".p7m", PKCS7);

        }
    }

现在......我如何提取与签名相关联的图像(位图)?可能吗? 谢谢,路易吉

1 个答案:

答案 0 :(得分:4)

在您的示例文档中,术语签名适用于三个:

  1. 它包含根据PDF规范ISO 32000-1:2008的数字签名。
  2. 相应的可视化包含手写签名的位图图像。
  3. 相应的签名字典包含软件的专有信息,该软件将所有签名数据添加到PDF。这些专有信息很可能包含OP评论中提到的生物特征数据。
  4. 根据创建这些多级签名的软件的制造商,手写签名似乎是身份的主要证明。数字文件仅用于保护文档免受更改;它不一定反映手动签名的人的身份,而不是创建该手册签名的设备的所有者(“请在这里签名表明您已获得包裹”):

      

    <强>功能

         

    手写签名捕获 - 签名板,支付终端,iPad或Android设备上的法定可识别签名。

         

    签名验证 - 将手写签名与预先注册的个人资料进行比较。

         

    控制签名过程中的所有步骤 - 包括定位签名字段,填写表单,添加注释,添加附件等等。

         

    保护文档的完整性 - 用数字签名密封它们。

         

    xyzmo English website start page

    关于使用iText提取所有这些信息......

    1. 使用AcroFields类的签名相关方法,OP已经观察到,可以轻松提取和验证数字签名的属性。
    2. 也可以相当容易地提取手写签名的位图图像。签名表单字段字典的外观流仅绘制作为资源附加到流的位图。
    3. 还可以提取包含专有信息的数据容器,因为它只是签名词典中另一个键的值。
    4. 不幸的是,该数据容器的内容被打包到一个称为 EncryptedSignatureDataContainer 的XML片段中。此XML片段的有效负载数据是否可以正确解密以及如何解释它是从xyzmo人员自己请求的信息,我不知道他们是否公开这些信息。
    5. 因此,最相关的信息是最不易获取的信息。

      PS 关于加密的生物识别有效负载的解密,我在制造商的网站上发现了以下内容:

        

      该文档包含已加密的已捕获签名(RSA 4096 + AES256)。一个人的签名在签名板使用特殊证书的私钥捕获时立即被加密。该特殊证书由公司使用xyzmo套件选择,通常存储在公司外部的安全环境中(银行保险箱,外部公证等)。因此,xyzmo本身无法访问此证书。对于签名加密,xyzmo套件只需要证书的公钥。它仅用于解密,以及从文档中提取签名,即需要私钥。只有公司授予其访问权限的特定人员才能使用PenAnalyst工具解密配置文件,该工具是套件的一部分。

           

      xyzmo English website Digital Signature Capture FAQ's

      因此,要解密生物识别数据,您必须能够访问相应的私钥,通常存储在公司外部的安全环境中(银行保险,外部公证等)。如果如果您有这种访问权限,我们可能会继续讨论这些解密数据的格式......;)

      顺便说一句,如果有人可以简单地从签名文档中检索生物识别数据,那么很容易将它们复制到其他文档来伪造签名。

      提取手写签名的位图图像

      由于对提取手写签名的位图图像特别感兴趣,因此这里有一个快速而又脏的帮助器来提取签名图像。正如已经说过的那样,我在Java中这样做,因为我更喜欢在那里:

      public class XyzmoSignatureDataExtractor
      {
          public XyzmoSignatureDataExtractor(PdfReader reader)
          {
              this.reader = reader;
          }
      
          public PdfImageObject extractImage(String signatureName) throws IOException
          {
              MyImageRenderListener listener = new MyImageRenderListener();
      
              PdfDictionary sigFieldDic = reader.getAcroFields().getFieldItem(signatureName).getMerged(0);
              PdfDictionary appearancesDic = sigFieldDic.getAsDict(PdfName.AP);
              PdfStream normalAppearance = appearancesDic.getAsStream(PdfName.N);
      
              PdfDictionary resourcesDic = normalAppearance.getAsDict(PdfName.RESOURCES);
      
              PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener);
              processor.processContent(ContentByteUtils.getContentBytesFromContentObject(normalAppearance), resourcesDic);        
      
              return listener.image;
          }
      
          class MyImageRenderListener implements RenderListener
          {
              public void beginTextBlock() { }
      
              public void endTextBlock() { }
      
              public void renderImage(ImageRenderInfo renderInfo)
              {
                  try
                  {
                      image = renderInfo.getImage();
                  }
                  catch (IOException e)
                  {
                      throw new RuntimeException("Failure retrieving image", e);
                  }
              }
      
              public void renderText(TextRenderInfo renderInfo) { }
      
              PdfImageObject image = null;
          }
      
          final PdfReader reader;
      }
      

      你这样使用它:

      PdfReader reader = new PdfReader(resourceStream);
      XyzmoSignatureDataExtractor extractor = new XyzmoSignatureDataExtractor(reader);
      AcroFields acroFields = reader.getAcroFields();
      
      for (String name: acroFields.getSignatureNames())
      {
          System.out.printf("\nTesting signature '%s'.\n", name);
          PdfImageObject image = extractor.extractImage(name);
      
          OutputStream os = new FileOutputStream("target/test-outputs/SampleXyzmoSignature-image-" + name + "." + image.getFileType());
          os.write(image.getImageAsBytes());
          os.close();
      
          PdfDictionary imageDictionary = image.getDictionary();
          PRStream maskStream = (PRStream) imageDictionary.getAsStream(PdfName.SMASK);
          if (maskStream != null)
          {
              PdfImageObject maskImage = new PdfImageObject(maskStream);
      
              os = new FileOutputStream("target/test-outputs/SampleXyzmoSignature-image-" + name + "-mask." + maskImage.getFileType());
              os.write(maskImage.getImageAsBytes());
              os.close();
          }
      }
      

      警告:班级XyzmoSignatureDataExtractor确实是一个快速而又肮脏的黑客攻击。做出了许多假设,null - 遗漏了支票,......