如何解决如何使用 itext7 将外部生成的签名应用于 PDF?
我正在尝试将第三方 AATL 服务生成的签名应用于 PDF。
我觉得我在调用所有内容几乎正确,但不出所料,当我查看签名文档时,我被告知签名无效。在这个过程中有很多步骤可能会出错,正如我正在学习的那样,这种绊脚石是意料之中的。 ?
无论如何,我正在寻找一些指导并填补我的知识空白。在编写代码之前,我会列出我认为需要回答的问题,您也可以在代码的注释中看到它们:
- 看起来我的摘要使用了正确的来源吗?即
data
? - 如果来源正确,我是否使用正确的技术来生成摘要?即,
DigestAlgorithms.digest(...)
? - 我调用的第三方服务返回的签名是 base64 编码的。在将表示作为
ByteArray
返回之前,我是否需要将其从 base64 转换为其他内容? - 我知道我必须以某种方式使用他们提供给我的证书,我只是不确定在哪里或如何使用?
- 签名人
fieldName
是什么? - 如何确定用于
8192
的estimatedSize
参数的signer.signExternalContainer
的正确值? - 如何将 CRL/OCSP 信息添加到 PDF?使用第三方 AATL 签名服务时,它通常来自哪里?
请随时指出不在上面列表中的任何其他建议或错误!??
data class ThirdPartyCertificateResponse(val certs: List<String>)
data class ThirdPartySigningResponse(val sig: String,val nonce: String)
class ThirdPartySignatureContainer : IExternalSignatureContainer {
private lateinit var data: ByteArray
override fun sign(data: InputStream): ByteArray {
// note: I've omitted any validation of the nonce from this sample.
val nonce = UUID.randomUUID()
val digest = DigestAlgorithms.digest(data,BouncyCastleDigest().getMessageDigest("sha256"))
// note: The service I'm calling expects requests to look like this.
// I'm including this on the offchance that I'm accidentally
// corrupting any of the data that I'm preparing for them.
val bodyJson = JWSObject(
JWSHeader(JWSAlgorithm.HS256),Payload(
mapOf<String,Any>(
// note: `digestInfo` is an extension method that returns an `org.bouncycastle.asn1.x509.DigestInfo` instance from a `ByteArray`
// note: Would love a tool that generates digests for me to check mine against! Hard to kNow if I'm doing the right thing here by basing it off of `data`??
"digestInfo" to digest.digestInfo().toBase64String(),"nonce" to nonce.toString(),"version" to 1,)
)
)
bodyJson.sign(MACSigner("SHARED_SECRET"))
val (_,_,signatureResult) = "https://thidpartyservice.notreal/api/v1/signatures"
.httpPost()
.body(bodyJson.serialize())
.responSEObject<ThirdPartySigningResponse>()
val signatureText = when (signatureResult) {
is Result.Failure -> throw signatureResult.getException()
is Result.Success -> signatureResult.value.sig
}
return signatureText.decodeBase64()
?: throw Exception("Unable to decode response from third party service")
}
override fun modifySigningDictionary(dictionary: PdfDictionary) {
val (_,certificateResult) = "https://thidpartyservice.notreal/api/v1/certs"
.httpGet()
.responSEObject<ThirdPartyCertificateResponse>()
val certificateFactory = CertificateFactory.getInstance("x.509")
// note: I have no idea what to do with these,but I've got them!
val certificateChain = when (certificateResult) {
is Result.Failure -> throw certificateResult.getException()
is Result.Success -> certificateResult.value.certs.map {
certificateFactory.generateCertificate(it.decodeBase64()?.inputStream())
}
}
// note: What are these doing?
dictionary.put(PdfName.Filter,PdfName.Adobe_PPKLite)
dictionary.put(PdfName.SubFilter,PdfName.Adbe_pkcs7_detached)
// note: I feel like I should be adding the certificate(s) to `dictionary` here...?
}
}
val stampingProperties = StampingProperties()
val signer = PdfSigner(thisPdfReader,thisSigned.outputStream(),stampingProperties)
// note: What's this?
signer.fieldName = null
signer.signatureAppearance
.setPageRect(Rectangle(0.0f,0.0f,0.0f))
.setPageNumber(1)
val container: IExternalSignatureContainer = ThirdPartySignatureContainer()
// note: I don't kNow how to determine a correct value for it,so I've left 8192 in here from examples I've seen.
signer.signExternalContainer(container,8192)
This is a sample of a PDF 我目前正在生成。
解决方法
您的 class ThirdPartySignatureContainer
实现了 IExternalSignatureContainer
;因此,它的 sign
方法应该返回一个 CMS 签名容器以原样嵌入到 PDF 中。但是,检查 your example file,很明显您的远程签名服务 - 以及您的 sign
方法 - 返回裸签名字节。
因此,您应该改为实现 IExternalSignature
的 sign
方法,该方法预期返回裸签名字节。要签名,您将使用 signer.signDetached
重载而不是 signer.signExternalContainer
。
这也意味着您的问题的答案如何将 CRL/OCSP 信息添加到 PDF - signDetached
重载具有 ICrlClient
和 IOcspClient
参数,也可以提供 CRL 和 OCSP 响应以进行嵌入。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。