PDF 签名 (Signature)
PDF 签名用于创建和签署 PDF 文档的数字签名,以保护文档内容的安全性和完整性。通过数字签名,接收者可以验证文档的来源和内容是否被篡改。福昕 PDF SDK 提供 API,支持创建数字签名、验证签名有效性、删除现有签名、获取和设置签名属性,以及自定义签名表单域的外观。
福昕 PDF SDK 提供默认签名回调函数,支持以下两种类型的 signature filter 和 subfilter:
- filter: Adobe.PPKLite,subfilter: adbe.pkcs7.detached
- filter: Adobe.PPKLite,subfilter: adbe.pkcs7.sha1
使用以上任意一种 signature filter 和 subfilter,您无需注册自定义回调函数,即可直接签名 PDF 文档并验证签名有效性。
如何对 PDF 文档进行签名,并验证签名
js
import { FoxitRDKNative } from 'foxit_rdk';
class SignatureUnit {
// 示例代码展示了如何对PDF文档进行签名,并验证签名
public addNewSignatureAndSign(page: FoxitRDKNative.pdf.PDFPage, rect: FoxitRDKNative.common.fxcrt.RectF): void {
try {
// 在指定的页面矩形上添加一个新的签名
const signature = page.AddSignature(rect);
// 设置 appearance flags
signature.SetAppearanceFlags(FoxitRDKNative.pdf.Signature.e_APFlagLabel |
FoxitRDKNative.pdf.Signature.e_APFlagDN |
FoxitRDKNative.pdf.Signature.e_APFlagText | FoxitRDKNative.pdf.Signature.e_APFlagLocation |
FoxitRDKNative.pdf.Signature.e_APFlagReason | FoxitRDKNative.pdf.Signature.e_APFlagSigner);
// 设置 signer
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameSigner, "Foxit");
// 设置 location
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameLocation, "AnyWhere");
// 设置 reason
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameReason, "ANyReason");
// 设置 contact info
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameContactInfo, "AnyInfo");
// 设置 domain name
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameDN, "AnyDN");
// 设置 description
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameText, "AnyContent");
// 默认支持 "Adobe.PPKLite" Filter
signature.SetFilter("Adobe.PPKLite");
// 默认支持 "adbe.pkcs7.sha1" 或 "adbe.pkcs7.detached" SubFilter
signature.SetSubFilter("adbe.pkcs7.detached");
// 输入的 PKCS#12 格式证书,其包含公钥和私钥
const certPath = "/somewhere/cert.pfx";
// 该证书的密码
const certPassword = "123";
const signedPDFPath = "/somewhere/signed.pdf";
// 开始签名,如果成功,签名后的PDF将保存到 "save_path" 指定的路径
class PauseCallBackImpl extends FoxitRDKNative.common.PauseCallback {
NeedToPauseNow(): boolean {
return false;
}
}
const progressive =
signature.StartSign(certPath, certPassword, FoxitRDKNative.pdf.Signature.e_DigestSHA1, signedPDFPath,
new ArrayBuffer(0), new PauseCallBackImpl());
if (progressive != null) {
let state = FoxitRDKNative.common.Progressive.e_ToBeContinued;
while (state == FoxitRDKNative.common.Progressive.e_ToBeContinued) {
state = progressive.Continue();
}
if (state != FoxitRDKNative.common.Progressive.e_Finished) {
return;
}
}
// 从已签名的PDF文档中获取签名,然后进行验证
const pdfDoc = new FoxitRDKNative.pdf.PDFDoc(signedPDFPath);
const err = pdfDoc.Load(null);
if (err != FoxitRDKNative.common.ErrorCode.e_ErrSuccess) {
return;
}
const count = pdfDoc.GetSignatureCount();
for (let i = 0; i < count; i++) {
const sign = pdfDoc.GetSignature(i);
if (sign != null && !sign.IsEmpty()) {
const progressive_1 = sign.StartVerify(new ArrayBuffer(0), null);
if (progressive_1 != null) {
let state = FoxitRDKNative.common.Progressive.e_ToBeContinued;
while (state == FoxitRDKNative.common.Progressive.e_ToBeContinued) {
state = progressive_1.Continue();
}
if (state != FoxitRDKNative.common.Progressive.e_Finished) {
continue;
}
}
const verifiedState = sign.GetState();
if ((verifiedState & FoxitRDKNative.pdf.Signature.e_StateVerifyValid) ==
FoxitRDKNative.pdf.Signature.e_StateVerifyValid) {
console.info("Signature", "addNewSignatureAndSign: Signature" + i + "is valid.");
}
}
}
} catch (e) {
console.error(e);
}
}
}
如何为签名设置定制化时间信息
通过 Signature 对象的 SetSignTime
方法不能改变时间格式。我们可以通过传递参数(时间字符串)给签名词典来解决这个问题。具体参考下述代码。
js
import { FoxitRDKNative } from 'foxit_rdk';
class SignatureUnit2 {
public addNewSignatureAndSign(page: FoxitRDKNative.pdf.PDFPage, rect: FoxitRDKNative.common.fxcrt.RectF): void {
try {
// 在指定的页面矩形上添加一个新的签名
const signature = page.AddSignature(rect);
// 设置 appearance flags
signature.SetAppearanceFlags(FoxitRDKNative.pdf.Signature.e_APFlagLabel |
FoxitRDKNative.pdf.Signature.e_APFlagDN |
FoxitRDKNative.pdf.Signature.e_APFlagText | FoxitRDKNative.pdf.Signature.e_APFlagLocation |
FoxitRDKNative.pdf.Signature.e_APFlagReason | FoxitRDKNative.pdf.Signature.e_APFlagSigner |
FoxitRDKNative.pdf.Signature.e_APFlagSigningTime);
// 设置 signer
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameSigner, "Foxit");
// 设置 location
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameLocation, "AnyWhere");
// 设置 reason
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameReason, "ANyReason");
// 设置 contact info
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameContactInfo, "AnyInfo");
// 设置 domain name
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameDN, "AnyDN");
// 设置 description
signature.SetKeyValue(FoxitRDKNative.pdf.Signature.e_KeyNameText, "AnyContent");
// DateTime dateTime = new DateTime();
// ...
// signature.SetSignTime(dateTime);
// 签名日期的默认格式是yyMMddhhmmss-时区
// 如果您需要设置自定义格式的时间,请参考以下代码
const dictionary = signature.GetSignatureDict();
dictionary.SetAtString("M", "2022/02/13 11:00:00"/* formatted time string*/);
// 默认支持 "Adobe.PPKLite" Filter
signature.SetFilter("Adobe.PPKLite");
// 默认支持 "adbe.pkcs7.sha1" 或 "adbe.pkcs7.detached" SubFilter
signature.SetSubFilter("adbe.pkcs7.detached");
// 输入的 PKCS#12 格式证书,其包含公钥和私钥
const certPath = "/somewhere/cert.pfx";
// 该证书的密码
const certPassword = "123";
const signedPDFPath = "/somewhere/signed.pdf";
// 开始签名,如果成功,签名后的PDF将保存到 "save_path" 指定的路径
class PauseCallBackImpl extends FoxitRDKNative.common.PauseCallback {
NeedToPauseNow(): boolean {
return false;
}
}
const progressive =
signature.StartSign(certPath, certPassword, FoxitRDKNative.pdf.Signature.e_DigestSHA1, signedPDFPath,
new ArrayBuffer(0), new PauseCallBackImpl());
if (progressive != null) {
let state = FoxitRDKNative.common.Progressive.e_ToBeContinued;
while (state == FoxitRDKNative.common.Progressive.e_ToBeContinued) {
state = progressive.Continue();
}
if (state != FoxitRDKNative.common.Progressive.e_Finished) {
return;
}
}
// 从已签名的PDF文档中获取签名,然后进行验证
const pdfDoc = new FoxitRDKNative.pdf.PDFDoc(signedPDFPath);
const err = pdfDoc.Load('');
if (err != FoxitRDKNative.common.ErrorCode.e_ErrSuccess) {
return;
}
const count = pdfDoc.GetSignatureCount();
for (let i = 0; i < count; i++) {
const sign = pdfDoc.GetSignature(i);
if (sign != null && !sign.IsEmpty()) {
const progressive_1 = sign.StartVerify(null, null);
if (progressive_1 != null) {
let state = FoxitRDKNative.common.Progressive.e_ToBeContinued;
while (state == FoxitRDKNative.common.Progressive.e_ToBeContinued) {
state = progressive_1.Continue();
}
if (state != FoxitRDKNative.common.Progressive.e_Finished) {
continue;
}
}
const verifiedState = sign.GetState();
if ((verifiedState & FoxitRDKNative.pdf.Signature.e_StateVerifyValid) ==
FoxitRDKNative.pdf.Signature.e_StateVerifyValid) {
console.info("Signature", "addNewSignatureAndSign: Signature" + i + "is valid.");
}
}
}
} catch (e) {
console.error(e);
}
}
}