为什么pdfbox成功地签署了pdf文件,但当在reader中打开时,它说文件在签署后被更改了?

iq0todco  于 2021-09-13  发布在  Java
关注(0)|答案(0)|浏览(367)

我正在使用pdfbox 2.0.22覆盖和签署文档。覆盖层工作正常,但签名表示文档自签名后已被更改。
我在macbook上通过smb访问pdf,并在linux上开发。
这是覆盖和签名的(剥离)功能:

public MergePdfResponse MergePdfs(MergePdfRequest mergePdfRequest) throws IOException {
    PdDocumentDetail basePdf = getPDFObject(getBasePdfBaseFileRequest());
    PdDocumentDetail overlayPdf = getPDFObject(getSignatureBaseFileRequest());

    PDDocument baseDocument = basePdf.pdDocument;
    PDDocument overlayDocument = overlayPdf.pdDocument;

    Iterator<PDPage> baseDocumentIterator = baseDocument.getPages().iterator();
    Iterator<PDPage> signatureIterator = overlayDocument.getPages().iterator();

    // code here to lock annotations per page

    Overlay overlay = new Overlay();
    overlay.setOverlayPosition(Overlay.Position.FOREGROUND);
    overlay.setInputPDF(baseDocument);
    overlay.setAllPagesOverlayPDF(overlayDocument);

    Map<Integer, String> ovmap = new HashMap<Integer, String>();
    overlay.overlay(ovmap);
    if(baseDocument.getPages().getCount() < overlayDocument.getPages().getCount()) //missing audit trail pages, need to add.
    {
        for(int i=baseDocument.getPages().getCount();i<overlayDocument.getPages().getCount(); i++)
        {
            baseDocument.addPage(overlayDocument.getPages().get(i));
        }
    }

    Config cfg = new Config();
    String secret = "1234";
    SetPermissions(baseDocument, secret, mergePdfRequest.canCopy);

    PDDocument finalDocument;
    try (ByteArrayOutputStream outputDocument = new ByteArrayOutputStream()) {
        baseDocument.saveIncremental(outputDocument);
        finalDocument = PDDocument.load(outputDocument.toByteArray(), secret);
        baseDocument.close();
    }

    int accessPermissions = SigUtils.getMDPPermission(finalDocument);
    if (accessPermissions == 1)
    {
        throw new IllegalStateException("No changes to the document are permitted due to DocMDP transform parameters dictionary");
    }

    PDSignature pdSignature = new PDSignature();
    pdSignature.setName("QuicklySign");
    pdSignature.setLocation("Cape Town, ZA");
    pdSignature.setReason("Testing");
    pdSignature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
    pdSignature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);

    SignatureOptions signatureOptions = new SignatureOptions();
    signatureOptions.setPreferredSignatureSize(SignatureOptions.DEFAULT_SIGNATURE_SIZE * 2);
    finalDocument.addSignature(pdSignature, new PdfSigningInterface(), signatureOptions);

    String filename = "examples/merge_pdf_examples/debug_signed.pdf";
    if(mergePdfRequest.isDebug) {
        filename = basePdf.filename + new Date().getTime() + ".ignore.pdf";
    }

    try (FileOutputStream output = new FileOutputStream(filename)) {
        finalDocument.saveIncremental(output);
    }
    finalDocument.close();
    overlayDocument.close();

    return new MergePdfResponse(mergePdfRequest.baseGcsBucket, filenameForCompleted);
}

pdfsigninginterface的代码:

public class PdfSigningInterface implements SignatureInterface {
    @Override
    public byte[] sign(InputStream inputStream) throws IOException {
        try {
            Certificate[] certificateChain = GoogleCertificateProvider.INSTANCE.buildCertificateChain();

            CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
            X509Certificate signingCertificate = (X509Certificate) certificateChain[0];

            ContentSigner googleContentSigner = new GoogleContentSigner();

            gen.addSignerInfoGenerator(
                    new JcaSignerInfoGeneratorBuilder(
                            new JcaDigestCalculatorProviderBuilder().build()
                    ).build(googleContentSigner, signingCertificate)
            );

            gen.addCertificates(new JcaCertStore(Arrays.asList(certificateChain)));

            CMSProcessableInputStream msg = new CMSProcessableInputStream(inputStream);
            CMSSignedData signedData = gen.generate(msg, false);

            return signedData.getEncoded();
        } catch (CMSException | OperatorCreationException | CertificateException e) {
            throw new IOException(e);
        }
    }
}

googlecontentsigner:

public class GoogleContentSigner implements ContentSigner {
    private final ByteArrayOutputStream outputStream;
    private final AlgorithmIdentifier sigAlgId;

    public GoogleContentSigner(){
        this.sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WITHRSAANDMGF1");
        this.outputStream = new ByteArrayOutputStream();
    }

    @Override
    public AlgorithmIdentifier getAlgorithmIdentifier() {
        return this.sigAlgId;
    }

    @Override
    public OutputStream getOutputStream() {
        return this.outputStream;
    }

    @Override
    public byte[] getSignature() {
        try {
            GoogleCertificateProvider kms = GoogleCertificateProvider.INSTANCE;

            byte[] signedAttributeSet = outputStream.toByteArray();
            Digest digest = kms.digestMessage(signedAttributeSet);

            return kms.signDigestedContent(digest);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("Unable to sign with KMS");
        }
    }
}

我的代码只是签名代码,而且我对pdfbox(或一般的pdf操作)非常陌生。我的目标是使用云kms生成签名pdf。
附有签名的pdf示例
为什么读者会这样说我的pdf签名是无效的?我直接登录到一个文件,并尝试在reader中打开它

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题