随着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和证书签名→Signed Base64 PDF(发送)到REST)


[1] https://github.com/diafygi/webcrypto-examples

[2] https://pkijs.org/



#1 楼

实际上,这样做是可行的,实际上,这是我们制作PKIjs时想到的场景之一(这就是为什么有此示例的原因)-https://pkijs.org/examples/PDFexample.html

要进行签名,需要使用PDF结构本身,这需要自定义解析器或对现有解析器进行修改(例如pdfjs)。

长话短说,签名浏览器中的PDF需要大量工作,但这是我们正在努力的工作。

评论


我想对纯文本签名,所以这个库可以吗?我没有找到可以读取p12证书+私钥并产生签名的示例。

– Michael Chourdakis
16年7月3日在10:59

您可以使用它进行签名。本示例对任意文件进行签名-pkijs.org/examples/CMSSigned_complex_example.html本示例显示了导入PKCS#12s-pkijs.org/examples/PKCS12SimpleExample.html有关某些限制和实现说明,请参见unmitigatedrisk.com/?p=543。

–rmhrisk
16年7月4日在20:37



#2 楼

披露:我为CISPL工作。
到目前为止,WebCrypto API不能提供对(Windows)或任何其他密钥存储区或本地加密USB /智能卡设备的访问。
在大多数签名方案中,由于需要在服务器范围内保护pdf文件,因此不建议将完整的pdf文件发送到浏览器或签名API服务器。
因此,其优良作法是创建PDF哈希以进行签名,将哈希发送给浏览器和通过浏览器扩展使用JavaScript来访问在本地系统上运行的某些应用程序,以访问本地密钥库(或USB /智能卡)并生成签名,并将其发送回服务器(在PDF签名的情况下为PKCS7或CMS容器),在服务器上可以注入签名
对于基于浏览器的签名方案,我公司提供了一个这样的免费浏览器扩展Signer.Digital和.NET库,它是服务器上所需的。可以从cNET下载站点下载本地系统(在Windows的chrome浏览器后运行的主机)
安装此主机并重新启动Chrome会自动添加Signer.Digital Chrome扩展程序和/或Signer.Digital Firefox扩展程序
此处说明了此扩展程序的实际工作原理,并提供了完整的代码演练并下载了VS 2015项目源代码示例的下载链接。
从扩展程序中调用方法的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 Error:”开头。
来自浏览器的数字签名


评论


“它的优良作法...”-好,优良作法取决于您更信任哪个应用程序。您的答案假设服务器应用程序是可信任的,可以为用户确实希望签名的pdf提供哈希值。对于第一次使用某个服务器应用程序的用户碰巧在计算机上拥有他信任的签名应用程序的用户,此假设可能不正确。

–mkl
19-4-23在15:13



@mki,我说的是在服务器上生成pdf。如果用户在自己的计算机上具有PDF,则可以使用许多工具,包括最常用的Acrobat Reader来对PDF文档进行签名...但是问题在于使用JavaScript进行签名,这意味着文档位于服务器上,而签名位于浏览器上。

–巴拉特·瓦森(Barat Vasant)
19年4月23日在17:36

“我说的是在服务器上生成pdf。” -即使这样,如果我不信任该服务器向我发送正确的哈希值,我(作为用户)也希望能够通过下载pdf,使用受信任的软件在本地对其进行签名,然后上传pdf来应用签名。再次签署pdf。不过,我不得不承认,任意浏览器扩展在这里并没有真正被视为受信任的软件,因此在这里,用例仅向我传输哈希还是整个文档就无关紧要了。

–mkl
19年4月23日在20:59

我在公司Web应用程序(例如CRM或基于Web的会计软件)上准备的由我准备的发票或PO上签名的一些示例,最后我想签字。另一个例子是eReturn,我刚刚在我的公司Web应用程序或eReturn服务提供商的Web UI上进行了预览,那么我不喜欢在签名之前查看XML或Return的Json。将“良好做法”替换为“常见做法”?! :)

–巴拉特·瓦森(Barat Vasant)
19-4-24的0:05



无需更改任何内容。如果用户有理由信任所讨论的服务器(例如,获得适当的CC认证支持),则该解决方案确实具有其魅力。

–mkl
19年4月24日在5:46

#3 楼

有PDFSign.js,一个可以在浏览器中签名PDF文件的库。它使用伪造作为签名。如果PKI.js支持分离的pkcs7签名,那么应该很容易替换伪造。

#4 楼

您可以使用openpgp.js签名任何文件(包括pdf)

https://openpgpjs.org/openpgpjs/doc/#create-and-verify-detached-signatures

(向下滚动至“创建并验证分离的签名”)

以Uint8Array的形式读取文件并使用私钥对其进行签名。

评论


每当人们要签名并强调要签名pdf的事实时,他们通常意味着要使用集成的pdf签名而不是使用单独的分离的签名文件进行签名。对于可互操作的签名,这意味着基于X.509证书的PKCS#1 / PKCS#7格式,而不是PGP格式。

–mkl
19/12/31在18:15