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

文档签名后已被更改或损坏

汲品
2023-03-14
public class ServerSignature implements ExternalSignature {
    public String getHashAlgorithm() {
      return DigestAlgorithms.SHA256;
    }
    public String getEncryptionAlgorithm() {
      return "RSA";
    }
    public byte[] sign(byte[] message) throws GeneralSecurityException {
      byte[] s = Base64.getDecoder().decode(SPMService.this.signature);
      return s;
    }
  }

public void sign(Certificate[] chain, CryptoStandard subfilter, String reason,
      String location) throws GeneralSecurityException, DocumentException, IOException {
    // Creating the reader and the stamper
    System.out.println("SRC: " + this.SRC);
    PdfReader reader = new PdfReader(this.SRC);
    FileOutputStream os = new FileOutputStream(this.DEST);
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
    // Creating the appearance
    PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
    appearance.setReason(reason);
    appearance.setLocation(location);

    appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");

    // Creating the signature
    ExternalDigest digest = new BouncyCastleDigest();
    ExternalSignature signature = new ServerSignature();
    MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);
    this.verifySignatures(this.DEST);
  } 

    private void verifySignature(AcroFields fields, String name) throws GeneralSecurityException, IOException {
    // Returns true
    System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
    // Returns the right revisions, e.g. 1 of 1
    System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
    PdfPKCS7 pkcs7 = fields.verifySignature(name);
    // Returns SHA256
    System.out.println("Digest algorithm: " + pkcs7.getHashAlgorithm());
    //Returns RSA
    System.out.println("Encryption algorithm: " + pkcs7.getEncryptionAlgorithm());
    // Return /adbe.pkcs7.detached
    System.out.println("Filter subtype: " + pkcs7.getFilterSubtype());
    // Get the signing certificate to find out the name of the signer.
    X509Certificate cert = (X509Certificate) pkcs7.getSigningCertificate();
    System.out.println("Name of the signer: " + CertificateInfo.getSubjectFields(cert).getField("CN"));
    if (pkcs7.getSignName() != null) {
      System.out.println("Alternative name of the signer: " + pkcs7.getSignName());
    }
    // The following log is returning false always. Why?
    System.out.println("Integrity check OK? " + pkcs7.verify());
  }
  private void verifySignatures(String src) throws IOException, GeneralSecurityException {
    Security.addProvider(new BouncyCastleProvider());
    PdfReader reader = new PdfReader(src);
    AcroFields fields = reader.getAcroFields();
    ArrayList<String> names = fields.getSignatureNames();
    for (String name : names) {
      System.out.println("===== " + name + " =====");
      verifySignature(fields, name);
    }
    System.out.println();
  }
  public void start() throws GeneralSecurityException, DocumentException, IOException {
    CertificateFactory factory = CertificateFactory.getInstance("X.509");
    // certificate I received in the Controller
    InputStream targetStream = new ByteArrayInputStream(this.certificate.getBytes());
    Certificate[] chain = new Certificate[1];
    chain[0] = factory.generateCertificate(targetStream);
    this.sign(chain, CryptoStandard.CMS, "Reason", "Location");
  }

共有1个答案

虞承泽
2023-03-14

问题不在你展示的代码中。因此,这要么是您使用的serversignature的问题,要么是它所寻址的服务器端代码的问题。

分析您分享的示例PDF可以看到:

>

  • PDF中带符号字节范围的SHA256摘要是

    37B415ACC3E5A146073E8C95D5DEE7E93190CF082210A9CE53AD78F7C5D58002
    
    . . . . . . SEQUENCE {
    . . . . . . . OBJECT IDENTIFIER messageDigest (1 2 840 113549 1 9 4)
    . . . . . . . . (PKCS #9)
    . . . . . . . SET {
    . . . . . . . . OCTET STRING    
    . . . . . . . . . 37 B4 15 AC C3 E5 A1 46    7......F
    . . . . . . . . . 07 3E 8C 95 D5 DE E7 E9    .>......
    . . . . . . . . . 31 90 CF 08 22 10 A9 CE    1..."...
    . . . . . . . . . 53 AD 78 F7 C5 D5 80 02                            
    . . . . . . . . }
    . . . . . . . }
    
    0083D5FA72C3D81EA038BF62D4AFFC949F23E120DA59E59C5CB8EFA5214BA975
    
    3031300D0609608648016503040201050004208DECC8571946D4CD70A024949E033A2A2A54377FE9F1C1B944C20F9EE11A9E51
    

    因此实际签名的SHA256摘要是

    8DECC8571946D4CD70A024949E033A2A2A54377FE9F1C1B944C20F9EE11A9E51
    

    显然存在不匹配。因此,在您使用的ExternalSignature实现ServerSignature中或在后端it地址中,签名的属性字节显然没有得到正确处理。

    不幸的是,您既没有显示您使用的serversignature实现代码,也没有显示服务器上的任何代码。因此,无法进一步分析目前的问题;很明显,您显示的iText签名代码工作正常。

    public class ServerSignature implements ExternalSignature {
        public String getHashAlgorithm() {
            return DigestAlgorithms.SHA256;
        }
        public String getEncryptionAlgorithm() {
            return "RSA";
        }
        public byte[] sign(byte[] message) throws GeneralSecurityException {
            byte[] s = Base64.getDecoder().decode(SPMService.this.signature);
            return s;
        }
    }
    

  •  类似资料:
    • 我正在使用PDFbox-1.8.8在PDF文件上做签名功能。 当我签署一份文件的时候 下面是我的代码:

    • 对于一个关于签名数据被哈希两次的C#问题,我看到了一个类似的答复,但是我不知道为什么我的签名数据会出现在这里。 C#PKCS7 Smartchard数字签名损坏

    • 我试图对pdf文件进行签名,但在Adobe中打开签名的pdf文件时,遇到“文档自签名后已被更改或损坏”错误。 这个错误不是那么描述性的,我不确定应该在哪里查看,因为代码对我来说似乎很好,但显然不是。。 我使用的代码是: 签名的哈希的Base64格式为(tmp文件sha_前缀): 签名(AMA)的Base64格式为: 有人能帮忙吗?

    • 我正在按代码创建一个签名PDF,但由于某种原因,我收到此错误: 至少一个签名无效-文档签名后已被更改或损坏 我将DSS属性与VRI、Certs和CRL一起使用。重要的一点是,我使用的版本与我在讨论此过程的其他文章中看到的版本相同。所以我有第一部分的签名(内容<>和byterange[])和第二部分与他的孩子的DSS。我注意到,如果删除第二个生成的部分,Adobe Acrobat将给出: 已签名且所

    • 我尝试使用智能卡(USB令牌)对pdf文件进行签名,但在Adobe中打开签名的pdf文件时,遇到错误。这个错误不是描述性的,我也不知道该去哪里看,因为代码对我来说似乎很好,但显然不是… 我使用的代码是: 我尝试签名的pdf文件是这个。 添加签名字段后创建的临时pdf文件如下。 签名的Base64格式为

    • 我正在为我的应用程序做一个PDF签名功能。以下是工作流程: PDF存储在服务器上。 我将所有必需的签名字段包含到文件中,并使用ZendPDF的扩展名为FaritPDF计算字节长度等。 我根据使用SHA256计算的字节长度计算哈希。 哈希将发送到客户端。 客户端使用PFX文件对哈希进行签名,并创建包含哈希的PKCS7对象。 将PKCS7对象发送到服务器。 PKCS7对象包含在PDF中,并呈现PDF。