PDFBOX锁定签名仍然可以添加具有有效状态的签名

发布于 2025-02-09 10:47:17 字数 5936 浏览 0 评论 0原文

请参阅我有关防止锁定后添加其他批准/签名的问题。在认证签名pdfbox 上添加锁定字典

我已经成功证明了锁定,但是在我尝试签署/添加另一个签名/批准的锁定之后,我的期望是锁定后,如果另一个符号锁定,则该文档已无效。

Rev 1-> Rev 2 - >认证 - >锁 - >然后Rev 4(来吧,仍然有效签名)

我尝试的是:

//Create empty signature field
PDDocument docEx=PDDocument.load(inputFile);
PDAcroForm acroFormField = docEx.getDocumentCatalog().getAcroForm();
acroFormField.getCOSObject().setNeedToBeUpdated(true);
COSObject fields = acroFormField.getCOSObject().getCOSObject(COSName.FIELDS);
if (fields != null)
    fields.setNeedToBeUpdated(true);

acroFormField.setSignaturesExist(true);
acroFormField.setAppendOnly(true);
acroFormField.getCOSObject().setDirect(true);

PDPage pageField = docEx.getPage(page);
// Create empty signature field, it will get the name "Signature1"
PDSignatureField signatureField = new PDSignatureField(acroFormField);
PDAnnotationWidget widget = signatureField.getWidgets().get(0);
PDRectangle rectField = new PDRectangle((float)humanRect.getX(), (float)humanRect.getY(), (float)humanRect.getWidth(), (float)humanRect.getHeight());
widget.setRectangle(rectField);
widget.getCOSObject().setNeedToBeUpdated(true);
widget.setPage(pageField);
pageField.getAnnotations().add(widget);
pageField.getCOSObject().setNeedToBeUpdated(true);
acroFormField.getFields().add(signatureField);
setLock(signatureField, acroFormField);
docEx.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
docEx.saveIncremental(fos);


fos.close();
//Close and replace with created empty field signature
PDDocument doc = PDDocument.load(signedFile);

FileOutputStream fosSeal = new FileOutputStream(signedFile);

PDSignature signatureLock = new PDSignature();
PDSignatureField signatureFieldLoad = (PDSignatureField) doc.getDocumentCatalog().getAcroForm().getField("Signature1");
LogSystem.info("signatureFieldLoad " + signatureFieldLoad.getValueAsString());
LogSystem.info("signaturelock " + signatureLock);
signatureFieldLoad.setValue(signatureLock);

COSBase lock = signatureFieldLoad.getCOSObject().getDictionaryObject(COS_NAME_LOCK);
if (lock instanceof COSDictionary)
{
    COSDictionary lockDict = new COSDictionary();
    lockDict.setItem(COS_NAME_ACTION, COS_NAME_ALL);
    lockDict.setItem(COSName.TYPE, COS_NAME_SIG_FIELD_LOCK);

    COSDictionary transformParams = new COSDictionary(lockDict);
    transformParams.setItem(COSName.TYPE, COSName.getPDFName("TransformParams"));
    transformParams.setItem(COSName.V, COSName.getPDFName("1.2"));
    transformParams.setInt(COSName.P, 1);

    transformParams.setDirect(true);
    transformParams.setNeedToBeUpdated(true);

    COSDictionary sigRef = new COSDictionary();
    sigRef.setItem(COSName.TYPE, COSName.getPDFName("SigRef"));
    sigRef.setItem(COSName.getPDFName("TransformParams"), transformParams);
    sigRef.setItem(COSName.getPDFName("TransformMethod"), COSName.getPDFName("FieldMDP"));
    sigRef.setItem(COSName.getPDFName("Data"), doc.getDocumentCatalog());
    sigRef.setDirect(true);
    COSArray referenceArray = new COSArray();
    referenceArray.add(sigRef);
    signatureLock.getCOSObject().setItem(COSName.getPDFName("Reference"), referenceArray);
    LogSystem.info("LOCK DICTIONARY");

    final Predicate<PDField> shallBeLocked;
    final COSArray fieldsLock = lockDict.getCOSArray(COSName.FIELDS);
    final List<String> fieldNames = fieldsLock == null ? Collections.emptyList() :
            fieldsLock.toList().stream().filter(c -> (c instanceof COSString)).map(s -> ((COSString)s).getString()).collect(Collectors.toList());
    final COSName action = lockDict.getCOSName(COSName.getPDFName("Action"));
    if (action.equals(COSName.getPDFName("Include"))) {
        shallBeLocked = f -> fieldNames.contains(f.getFullyQualifiedName());
    } else if (action.equals(COSName.getPDFName("Exclude"))) {
        shallBeLocked = f -> !fieldNames.contains(f.getFullyQualifiedName());
    } else if (action.equals(COSName.getPDFName("All"))) {
        shallBeLocked = f -> true;
    } else { // unknown action, lock nothing
        shallBeLocked = f -> false;
    }
    lockFields(doc.getDocumentCatalog().getAcroForm().getFields(), shallBeLocked);
    setMDPPermission(doc, signatureLock, 2);

    // default filter
    signatureLock.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);

    // subfilter for basic and PAdES Part 2 signatures
    signatureLock.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);

    signatureLock.setName(name);

    // the signing date, needed for valid signature
    signatureLock.setSignDate(getDate());

    // do not set SignatureInterface instance, if external signing used
    SignatureInterface signatureInterface = isExternalSigning() ? null : this;


    doc.addSignature(signatureLock, signatureInterface, signatureOptions);

    doc.getDocumentCatalog().getAcroForm().getField("Signature1").setPartialName(SignatureField);

    if (isExternalSigning()) {
        this.tsaUrl=tsaUrl;

        ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(fosSeal);

        // invoke external signature serviceUsing fallback
        byte[] cmsSignature =IOUtils.toByteArray(externalSigning.getContent());
        String sgn=null;
        try {
            sgn = signingProcess(cmsSignature);
        }catch(Exception e)
        {
            LogSystem.error(e.toString());
            e.printStackTrace();
            doc.close();
            Telegram tele = new Telegram();
            tele.Send(e.toString());
            return false;
        }

        // set signature bytes received from the service
        if (sgn != null)
        {
            externalSigning.setSignature(attachSignature(sgn));
        }
    }

有什么建议吗?还是任何人都可以告诉我,如果我想防止文件更改,它是如何工作的?谢谢

refer my question about prevent adding another approval/signing after lock Add lock Dictionary on Certify Signature PDFBox

i have succeed to certify then lock, but after lock when i try to signing/adding another signature/approval is still valid, what i expected is after lock if another sign the document becomes invalid

adobe

rev 1 -> rev 2 -> certified -> lock -> then rev 4 (come and still valid signature)

this what i'm try:

//Create empty signature field
PDDocument docEx=PDDocument.load(inputFile);
PDAcroForm acroFormField = docEx.getDocumentCatalog().getAcroForm();
acroFormField.getCOSObject().setNeedToBeUpdated(true);
COSObject fields = acroFormField.getCOSObject().getCOSObject(COSName.FIELDS);
if (fields != null)
    fields.setNeedToBeUpdated(true);

acroFormField.setSignaturesExist(true);
acroFormField.setAppendOnly(true);
acroFormField.getCOSObject().setDirect(true);

PDPage pageField = docEx.getPage(page);
// Create empty signature field, it will get the name "Signature1"
PDSignatureField signatureField = new PDSignatureField(acroFormField);
PDAnnotationWidget widget = signatureField.getWidgets().get(0);
PDRectangle rectField = new PDRectangle((float)humanRect.getX(), (float)humanRect.getY(), (float)humanRect.getWidth(), (float)humanRect.getHeight());
widget.setRectangle(rectField);
widget.getCOSObject().setNeedToBeUpdated(true);
widget.setPage(pageField);
pageField.getAnnotations().add(widget);
pageField.getCOSObject().setNeedToBeUpdated(true);
acroFormField.getFields().add(signatureField);
setLock(signatureField, acroFormField);
docEx.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
docEx.saveIncremental(fos);


fos.close();
//Close and replace with created empty field signature
PDDocument doc = PDDocument.load(signedFile);

FileOutputStream fosSeal = new FileOutputStream(signedFile);

PDSignature signatureLock = new PDSignature();
PDSignatureField signatureFieldLoad = (PDSignatureField) doc.getDocumentCatalog().getAcroForm().getField("Signature1");
LogSystem.info("signatureFieldLoad " + signatureFieldLoad.getValueAsString());
LogSystem.info("signaturelock " + signatureLock);
signatureFieldLoad.setValue(signatureLock);

COSBase lock = signatureFieldLoad.getCOSObject().getDictionaryObject(COS_NAME_LOCK);
if (lock instanceof COSDictionary)
{
    COSDictionary lockDict = new COSDictionary();
    lockDict.setItem(COS_NAME_ACTION, COS_NAME_ALL);
    lockDict.setItem(COSName.TYPE, COS_NAME_SIG_FIELD_LOCK);

    COSDictionary transformParams = new COSDictionary(lockDict);
    transformParams.setItem(COSName.TYPE, COSName.getPDFName("TransformParams"));
    transformParams.setItem(COSName.V, COSName.getPDFName("1.2"));
    transformParams.setInt(COSName.P, 1);

    transformParams.setDirect(true);
    transformParams.setNeedToBeUpdated(true);

    COSDictionary sigRef = new COSDictionary();
    sigRef.setItem(COSName.TYPE, COSName.getPDFName("SigRef"));
    sigRef.setItem(COSName.getPDFName("TransformParams"), transformParams);
    sigRef.setItem(COSName.getPDFName("TransformMethod"), COSName.getPDFName("FieldMDP"));
    sigRef.setItem(COSName.getPDFName("Data"), doc.getDocumentCatalog());
    sigRef.setDirect(true);
    COSArray referenceArray = new COSArray();
    referenceArray.add(sigRef);
    signatureLock.getCOSObject().setItem(COSName.getPDFName("Reference"), referenceArray);
    LogSystem.info("LOCK DICTIONARY");

    final Predicate<PDField> shallBeLocked;
    final COSArray fieldsLock = lockDict.getCOSArray(COSName.FIELDS);
    final List<String> fieldNames = fieldsLock == null ? Collections.emptyList() :
            fieldsLock.toList().stream().filter(c -> (c instanceof COSString)).map(s -> ((COSString)s).getString()).collect(Collectors.toList());
    final COSName action = lockDict.getCOSName(COSName.getPDFName("Action"));
    if (action.equals(COSName.getPDFName("Include"))) {
        shallBeLocked = f -> fieldNames.contains(f.getFullyQualifiedName());
    } else if (action.equals(COSName.getPDFName("Exclude"))) {
        shallBeLocked = f -> !fieldNames.contains(f.getFullyQualifiedName());
    } else if (action.equals(COSName.getPDFName("All"))) {
        shallBeLocked = f -> true;
    } else { // unknown action, lock nothing
        shallBeLocked = f -> false;
    }
    lockFields(doc.getDocumentCatalog().getAcroForm().getFields(), shallBeLocked);
    setMDPPermission(doc, signatureLock, 2);

    // default filter
    signatureLock.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);

    // subfilter for basic and PAdES Part 2 signatures
    signatureLock.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);

    signatureLock.setName(name);

    // the signing date, needed for valid signature
    signatureLock.setSignDate(getDate());

    // do not set SignatureInterface instance, if external signing used
    SignatureInterface signatureInterface = isExternalSigning() ? null : this;


    doc.addSignature(signatureLock, signatureInterface, signatureOptions);

    doc.getDocumentCatalog().getAcroForm().getField("Signature1").setPartialName(SignatureField);

    if (isExternalSigning()) {
        this.tsaUrl=tsaUrl;

        ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(fosSeal);

        // invoke external signature serviceUsing fallback
        byte[] cmsSignature =IOUtils.toByteArray(externalSigning.getContent());
        String sgn=null;
        try {
            sgn = signingProcess(cmsSignature);
        }catch(Exception e)
        {
            LogSystem.error(e.toString());
            e.printStackTrace();
            doc.close();
            Telegram tele = new Telegram();
            tele.Send(e.toString());
            return false;
        }

        // set signature bytes received from the service
        if (sgn != null)
        {
            externalSigning.setSignature(attachSignature(sgn));
        }
    }

any suggest ? or anyone can tell me how it work if i want to prevent the document changes ? thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文