Pdfbox 签名 - saveIncremental 与 saveIncrementalForExternalSigning

Pdfbox signing - saveIncremental vs saveIncrementalForExternalSigning

我正在为 pdf 文件签名,我有些担心。 从 pdfbox 示例中,我看到了两种签署 pdf 的方法。第一个是:

document.saveIncremental(output);

第二种方式:

ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(fos);
// invoke external signature service
byte[] cmsSignature = sign(externalSigning.getContent());

if (isLateExternalSigning()) {
    // this saves the file with a 0 signature
    externalSigning.setSignature(new byte[0]);
    // remember the offset (add 1 because of "<")
    int offset = signature.getByteRange()[1] + 1;
    // now write the signature at the correct offset without any PDFBox methods
    RandomAccessFile raf = new RandomAccessFile(signedFile, "rw");
    raf.seek(offset);
    raf.write(Hex.getBytes(cmsSignature));
    raf.close();
} else {
    // set signature bytes received from the service and save the file
    externalSigning.setSignature(cmsSignature);
}

saveIncrementalsaveIncrementalForExternalSigning有什么区别?我的意思是这些方法的用例。

每种方法的用途是什么?

什么是“增量”?

什么是“外签”?是政府之类的第三方吗?

什么是“增量”?

保存对 pdf 的更改时,有两种选择,一种可以保存一个全新的 pdf 文件,一种可以将更改附加到原始文件(的副本)中。后一种技术称为 增量更新.

再次签署已签名的 pdf 时,必须将此新签名的添加作为增量更新应用,以防止使现有签名无效:

(有关背景和参考资料,请参阅 this answer。)

因此,pdf 库需要支持在增量更新中签署 PDF

PDFBox,为简单起见,支持在增量更新中签署 PDF ,因此已经以这种方式添加了第一个签名。

saveIncrementalsaveIncrementalForExternalSigning有什么区别?

saveIncremental

使用 saveIncremental 创建签名的 pdf 使用回调来生成签名容器:您在 PDDocument.addSignature 调用中选择的 SignatureInterface 实现的方法 sign 是被 saveIncremental 用于检索要签名的文档字节的签名容器。

在 pdfbox 签名示例中,sign 方法在 CreateSignatureBase 中实现,并在 signPDF 中设置为签名接口。

saveIncrementalForExternalSigning

使用 saveIncrementalForExternalSigning 创建签名 pdf 不需要 SignatureInterface 实现。相反,它 returns 一个 ExternalSigningSupport 对象,您可以从中检索要签名的数据 (getContent) 然后您可以创建一个签名容器,您最终可以使用另一种 ExternalSigningSupport 方法 (setSignature).

到目前为止,这听起来只是一个支持不同编程模式偏好、回调与非回调、顺序的选项。

这里还有一个额外的选项, 也称为 延迟签名:您可以注入而不是注入实际的签名容器一个假人:

externalSigning.setSignature(new byte[0]);

并检索签名容器占位符(十六进制编码)所在的位置:

int offset = signature.getByteRange()[1] + 1;

因此,现在您可以计算要签名的哈希值,将文件和偏移量存储在例如一个数据库,并调用一些签名服务,而不必将 pdf 保存在内存中。

最终您可以像示例代码一样注入签名容器:

RandomAccessFile raf = new RandomAccessFile(signedFile, "rw");
raf.seek(offset);
raf.write(Hex.getBytes(cmsSignature));
raf.close();

这些方法的用例

如上所述,乍一看这两种方法只是支持不同的编程模式,回调和顺序。

不过,附加选项确实允许支持其他用例,在某些情况下特别方便:

  • 如果签名服务很慢,例如因为请求被批量收集和处理,或者因为等待第二个因素的确认。

  • 如果签名容器的检索和注入发生在与 pdf 准备不同的程序中,甚至可能是不同的计算机。

什么是“外签”?是政府之类的第三方吗?

这里的“外部”是指程序执行。虽然回调感觉非常 内部,但按顺序分开调用感觉不那么明显,延迟签名可以被视为真正的 外部.

第三方签名服务(无论是否为政府)都可以集成到任一架构中。根据他们的表现,延迟方法可能更可取。