随着WebCrypto API的发展和Chrome和Firefox的支持,我想用它来对PDF文档进行数字签名。周围没有太多的文献,但我找到了一些例子[1]和一个名为PKI.js的图书馆[2]。在示例中,描述了签名过程,但最终返回签名。我希望我的Base64 PDF文件在签名的Base64字符串中再次返回,但遗憾的是,这不是发生的事情。据我所知,PKI.js也没有提供签署我的Base64 PDF的方法。
有没有办法只使用JavaScript和WebCrypto API签署PDF?私钥可以在<textarea>
中输入,或者甚至更好地存储在浏览器的证书设置中。
Base64 PDF(来自REST API)→使用JS和证书签名→签名Base64 PDF(发送到REST)
在技术上可以做到这一点,事实上它是我们制作PKIjs时想到的场景之一(这就是为什么有这个样本) - https://pkijs.org/examples/PDFexample.html
那说要做签名需要使用PDF结构本身,要么需要自定义解析器,要么修改现有解析器(例如pdfjs)。
长话短说,在浏览器中签署PDF需要花费大量的工作,这是我们正在努力的事情。
有PDFSign.js,一个可以在浏览器中签署PDF文件的库。它使用forge作为签名。如果PKI.js支持分离的pkcs7签名,那么应该很容易替换伪造。
截至目前,WebCrypto API不提供对(Windows)或任何其他密钥存储或本地加密USB /智能卡设备的访问。
此外,在大多数签名方案中,为了保护服务器边界内的pdf文件的要求,不建议将完整的pdf文件发送到浏览器或签署API服务器。
因此,它的良好实践,创建用于签名的PDF哈希,向浏览器发送哈希并通过浏览器扩展使用javascript访问本地系统上运行的某些应用程序以访问本地密钥库(或USB /智能卡)并生成签名并发回(将PDF签名的PKCS7或CMS容器发送到服务器,其中签名可以注入PDF,从中创建用于签名的哈希并发送到浏览器或签署api服务器。
对于基于浏览器的签名方案,可以使用一个免费的Chrome扩展程序是Signer.Digital chrome扩展。可以从https://signer.digital/downloads/Signer.Digital.Chrome.Host.Setup.zip或cNET Download site下载本地系统(在Windows上运行Chrome浏览器后面的主机)安装此主机并重新启动Chrome将自动添加Signer.Digital Chrome Extension
here说明了这个扩展的实际工作情况
Javascript从扩展名调用方法:
//Calculate Sign for the Hash by Calling function from Extension SignerDigital
SignerDigital.signPdfHash(hash, $("#CertThumbPrint").val(), "SHA-256") //or "SHA256"
.then(
function (signDataResp) {
//Send signDataResp to Server
},
function (errmsg) {
//Send errmsg to server or display the result in browser.
}
);
如果成功,则返回Base64编码的pkcs7签名 - 使用合适的库或Signer.Digital提供的库将符号注入pdf
如果失败,则返回以“SDHost错误:”开头的错误消息