使用 Google KMS 在 Node JS 中进行 PDFNet 数字签名

问题描述

我见过签署https://www.pdftron.com/documentation/nodejs/guides/features/signature/sign-pdf的例子

signOnNextSave 使用 PKCS #12 证书,但我使用 Google KMS 进行非对称签名以确保私钥安全。

以下是通过 Google Cloud KMS 进行签名和验证的示例

我尝试实现自定义 SignatureHandler 但 Node.JS API 与 Java 或 .NET 不同 https://www.pdftron.com/api/pdfnet-node/PDFNet.SignatureHandler.html

如何实现自定义签名和验证逻辑?

const data = Buffer.from('pdf data')

// We have 2048 Bit RSA - PSS Padding - SHA256 Digest key in Google Cloud KMS
const signasymmetric = async () => {
  const hash = crypto.createHash('sha256')
  hash.update(data)
  const digest = hash.digest()
  const digestCrc32c = crc32c.calculate(digest)

  // Sign the data with Cloud KMS
  const [signResponse] = await client.asymmetricSign({
    name: locationName,digest: {
      sha256: digest
    },digestCrc32c: {
      value: digestCrc32c
    }
  })

  if (signResponse.name !== locationName) {
    throw new Error('asymmetricSign: request corrupted in-transit')
  }
  if (!signResponse.verifiedDigestCrc32c) {
    throw new Error('asymmetricSign: request corrupted in-transit')
  }
  if (
    crc32c.calculate(signResponse.signature) !==
    Number(signResponse.signatureCrc32c.value)
  ) {
    throw new Error('asymmetricSign: response corrupted in-transit')
  }

  // Returns signature which is buffer
  const encoded = signResponse.signature.toString('base64')
  console.log(`Signature: ${encoded}`)

  return signResponse.signature
}

// Verify data with public key
const verifyasymmetricSignatureRsa = async () => {
  const signatureBuffer = await signasymmetric()
  const publicKeyPem = await getPublicKey()

  const verify = crypto.createVerify('sha256')
  verify.update(data)
  verify.end()

  const key = {
    key: publicKeyPem,padding: crypto.constants.RSA_PKCS1_PSS_PADDING
  }

  // Verify the signature using the public key
  const verified = verify.verify(key,signatureBuffer)
  return verified
}

解决方法

目前,PDFTron SDK 仅支持 C++、Java 和 C# 上的自定义处理程序(未来有更多计划包含其他语言)。

在 C++ 等不同平台上,您可以通过将 hash.update(data) 放入 SignatureHandler::AppendData 来扩展自定义处理程序函数,而 signAsymmetric 的其余部分将放入 SignatureHandler::CreateSignature。将为互操作性的自定义处理程序命名,例如 Adobe.PPKLite(我们尚不支持自定义处理程序子过滤器条目,仅支持过滤器——请参阅 PDF 标准以了解区别——但这并不重要,只要您使用支持过滤器 Adobe.PPKLite 的验证工具)。请参阅以下链接以获取具体示例: https://www.pdftron.com/documentation/samples/cpp/DigitalSignaturesTest

至于验证,如果您的签名满足以下条件,我们的代码已经可以为您执行此操作:

  1. 他们使用标准的摘要算法
  2. 他们使用 RSA 进行签名
  3. 他们根据 PDF 标准使用正确的数据格式(即分离的 CMS、数字签名字典)

如果您有更多问题或需要更多详细信息,请随时通过 support@pdftron.com 联系 PDFTron 支持