使用纯 JavaScript 签署 PDF

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33216843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:47:43  来源:igfitidea点击:

Sign PDF with plain JavaScript

javascriptpdfsignsigningwebcrypto-api

提问by ssc-hrep3

With WebCrypto API evolving and being supported by Chrome and Firefox, I would like to use it for digitally signing a PDF document. There is not much of literature around, but I found some examples [1] and a library called PKI.js [2]. In the examples, the signing process is described, but in the end, a signature is returned. I would expect my Base64 PDF file returned again in a signed Base64 string, but sadly, this is not what happens. PKI.js too, to my knowledge, does not provide a way to sign my Base64 PDF.

随着 WebCrypto API 的发展并得到 Chrome 和 Firefox 的支持,我想用它来对 PDF 文档进行数字签名。周围的文献并不多,但我找到了一些示例 [1] 和一个名为 PKI.js [2] 的库。在示例中,描述了签名过程,但最终返回了签名。我希望我的 Base64 PDF 文件以已签名的 Base64 字符串再次返回,但遗憾的是,事实并非如此。据我所知,PKI.js 也不提供对我的 Base64 PDF 进行签名的方法。

Is there a way to sign a PDF with JavaScript and the WebCrypto API only? The private key can be entered in a <textarea>or, even better, stored in the certificate settings of the browser.

有没有办法只使用 JavaScript 和 WebCrypto API 签署 PDF?私钥可以输入<textarea>到浏览器的证书设置中,或者更好地存储在浏览器的证书设置中。

Base64 PDF (from REST API) → Sign with JS & certificate → Signed Base64 PDF (send to REST)

Base64 PDF(来自 REST API)→ 使用 JS 和证书签名→ 签名的 Base64 PDF(发送到 REST)

回答by rmhrisk

It is technically possible to do this, in-fact it is one of the scenarios we had in mind when we made PKIjs (which is why there is this sample) - https://pkijs.org/examples/PDFexample.html

在技​​术上可以做到这一点,事实上这是我们制作 PKIjs 时想到的场景之一(这就是为什么有这个示例) - https://pkijs.org/examples/PDFexample.html

That said to do signing requires working with the PDF structure itself, which either requires a custom parser or modifications to an existing one (pdfjs for example).

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

Long story short, signing a PDF in browser will take a lot of work, it is something we are working on though.

长话短说,在浏览器中签署 PDF 需要很多工作,但这是我们正在努力的事情。

回答by user3481465

There is PDFSign.js, a library that can sign a PDF file in the browser. It uses forgethough for the signature. If PKI.js supports detached pkcs7 signatures, then it should be easy to replace forge.

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

回答by Bharat Vasant

Disclosure: I work for CISPL.

披露:我为 CISPL 工作。

As of now, WebCrypto API does not provide access to (Windows) or any other Key stores or local crypto USB/Smartcard device.

截至目前,WebCrypto API 不提供对 (Windows) 或任何其他密钥库或本地加密 USB/智能卡设备的访问。

Also in most of the signing scenarios, for requirement to protect pdf file within the server boundaries, its not recommended to send complete pdf file to browser or to signing API server.

同样在大多数签名场景中,为了保护服务器边界内的 pdf 文件,不建议将完整的 pdf 文件发送到浏览器或签名 API 服务器。

Thus, its good practice, to create hash of PDF for signing, send hash to browser and use javascript through browser extension to access some application running on local system to access local keystore (or USB/Smartcard) and produce the signature and send back (PKCS7 or CMS container in case of PDF signing) to server where the signature may be injected back to PDF from which hash was created for signing and was sent to browser or to signing api server.

因此,它的良好做法是创建用于签名的 PDF 哈希值,将哈希值发送到浏览器并通过浏览器扩展使用 javascript 来访问在本地系统上运行的某些应用程序以访问本地密钥库(或 USB/智能卡)并生成签名并发回( PKCS7 或 CMS 容器(在 PDF 签名的情况下)到服务器,其中签名可以注入回 PDF,从中创建哈希用于签名并发送到浏览器或签名 api 服务器。

For browser based signing scenarios, my company provides one such free Browser extension Signer.Digital and .NET library required on server. Local system (host running behind the chrome browser on windows) may be downloaded from cNET Download siteInstalling this host and restarting Chrome will automatically add Signer.Digital Chrome Extension

对于基于浏览器的签名场景,我公司提供了一种服务器上所需的免费浏览器扩展 Signer.Digital 和 .NET 库。本地系统(Windows 上运行在 Chrome 浏览器后面的主机)可以从cNET 下载站点下载安装此主机并重新启动 Chrome 将自动添加Signer.Digital Chrome 扩展

The actual working of this extension is illustrated herealong with complete code walk through and download link to working sample VS 2015 project source code.

此处说明了此扩展的实际工作以及完整的代码演练和工作示例 VS 2015 项目源代码的下载链接。

Javascript to call method from extension:

从扩展调用方法的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.
           }
  );

If success, returns Base64 encoded pkcs7 signature - use suitable library or one provided by Signer.Digital to inject sign to pdf

如果成功,则返回 Base64 编码的 pkcs7 签名 - 使用合适的库或 Signer.Digital 提供的库将签名注入 pdf

If Failed, returns error msg starting with "SDHost Error:"

如果失败,则返回以“SDHost 错误”开头的错误信息:

Digital Signing from Browser

来自浏览器的数字签名

Digital Signing from Browser

来自浏览器的数字签名

回答by user2677034

You can sign any file (including pdf) using openpgp.js

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

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

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

(scroll down to 'create-and-verify-detached-signatures')

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

Read the file as a Uint8Array and sign it with your private key.

将文件作为 Uint8Array 读取并使用您的私钥对其进行签名。