With JavaScript in the browser, I need to digitally sign some data. I'm looking at the new Crypto.Subtle api, specifically the sign() and importKey() methods. I want, very reasonably I feel, to install a certificate on a mobile device, outside of my web app, then, in the web app, to sign some stuff with the installed certificate without directly manipulating or seeing the private key. However I can't see if or how the Crypto API interfaces with installed certificates.

Am I missing something obvious? If this is not possible, are there browser plugins that can help me? I see in 2009 someone did this with an MS ActiveX object, but there must be a better way six years later?


It's not possible, not without significant effort by browser authors (or browser plugin authors) to make it possible. Remember, the point of signing something is to verify that its authenticity - that is, that the signer meant to sign that thing, with that key, and they are the only one with the key - so having a way for web page content (which is inherently untrustworthy code, from a browser's point of view) to access a user's signing keys would be a major security risk! Even just enumerating installed keys would allow for user fingerprinting and tracking.

Now, a browser (or plugin) could attempt to do this securely, by offering a JS API that basically prompts the user "A script on site is attempting to access your certificate store. [Allow] [Deny (default)]" and then a similar prompt (if the first is approved) for access to your private key (and password for it if needed). I would be very cautious about such a feature, though.

  • I'm not the only one asking, and things seem to be moving in this direction, but I see at the moment it's not really possible in the browser.
    – bbsimonbb
    Sep 17 '15 at 10:16
  • Oh, I can definitely see the usefulness. For trusted sites, it would be extremely handy, and people are already working on things of this nature. It's just, the whole area is risky from a security and privacy standpoint, so any design safe enough to be made standard will take a while to flesh out.
    – CBHacking
    Sep 17 '15 at 19:08
  • Absolutely. And if we can't do it in the browser, we're pretty much obliged to go native, and native applications will not necessarily do a better job of safeguarding the user's interests.
    – bbsimonbb
    Sep 18 '15 at 8:43
  • Refer to this SO answer stackoverflow.com/a/63173083/9659885 for Javascript API reference of one of the free browser extension. May 21 at 10:57

Most of the web applications require Digital Signing documents, files, eReturns (XML or JSON) etc, from the user's browser using the user's local machine keystore, USB token or smartcard. Older methods being Java applets, Active X, etc. which are phased out or are being phased out from the new modern browser offerings.

Recently much is being talked about WebCrypto API but as of now, WebCrypto API does not provide access to Windows' or any other keystores or a local crypto USB/smartcard device.

Thus, it's good practice, to use JavaScript through a browser extension to access some application running on the local system to access the local KeyStore/CertificateStore and produce the signature and send it back (PKCS7 or CMS container in case of PDF signing) to the server where the signature may be injected back to the PDF from which the hash was created for signing, and was sent to the browser or to a signing API server.

One such free extension is provided by my company. Please refer Signer.Digital Browser Extension which points to a number of Stack Overflow answers providing JavaScript code to achieve different signing functions.

Refer to this SO Answer for details of all Javascript API for Signing, Encryption, Decryption, Certificate Enrollment and Certificate Download.

June 2021 Update Signer.Digital Browser Extension Host Version 1.7.0 now offers better user control to enhance security by asking user about Allowed Origin (website) which is trying to access certificates/keys. Also this version has Auto Update feature so that user automatically gets any security updates/enhancements after approving update by User Account Control dialog.

enter image description here

  • "as of now, WebCrypto API does not provide access to Windows' or any other keystores or a local crypto USB/smartcard device" - Just making sure: are you aware that there are EXTREMELY good reasons for this limitation? What safeguards does your extension offer to prevent malicious abuse and compromise of your private keys by random JS on the web? Unless there are extremely tight restrictions (default deny-all sites, allow only by explicit user action) on use of these APIs, or unambiguous and unavoidable user interaction required each time, this extension is a security disaster.
    – CBHacking
    May 21 at 11:27
  • I appreciate your concern. Though we suggest this to be used with Crypto Smartcard or USB Token which asks for passwords while doing key operations. Also on crxcavator.io we tried to get lowest risk for this extension in the category. This is just a tool... Most of the security onus of web application lies on the developer of the application. May 21 at 12:38
  • crxcavator.io is an automated vulnerability scanner. It detects common, implementation-based, web-based security vulns and excessive privileges. It CAN NOT detect, and doesn't even attempt to quantify, extensions that are not only insecure by design but use a Native Messaging component to demolish critical features of the browser security model!
    – CBHacking
    May 21 at 16:48
  • As for the rest of your comment, no, this is not "just a tool". A crowbar is just a tool. A crowbar that is mounted on the outside of your own house with a sign labeled "push here to open window" is a gaping security vulnerability. This extension is the latter. Combined with not understanding the threat model - it has nothing to do with web app security (because it is a BROWSER/OS VULNERABILITY that YOU ARE INTRODUCING) and there is literally no way to safely use it as a web dev without letting other web devs exploit it - is more evidence your company shouldn't even be in this space!
    – CBHacking
    May 21 at 16:54
  • Telling people "well, it's OK to install this extension if 100% of the private keys you have installed require a password every time they're used, even though that's not the default behavior of the Windows key storage" is just grossly inappropriate deflection of responsibility. If the extension refused to work for any private key that didn't have such protection, that would be reasonable, but if you merely "suggest" it then you are, at best, negligently messing with things you do not understand, and advertising them to people who don't know enough to keep themselves safe either.
    – CBHacking
    May 21 at 17:00

It's not possible in a plain browser. But if you try to run your web app, you will certainly use some kind of wrapper lib to convert it to android application (or ios, etc). This way you can do what your wrapper can do on the mobile device. If you write your own wrapper, and you have the proper rights, you can do anything what other mobile apps can do.

Most popular wrapper like phoneGap gives you api for file access, this way you can access your key (btw, signing is done by privkey not by certificates).

However I agree with CBHacking, it wouldnt be a very wise idea to access your precious keys from javascript. Maybe a better approach to create some API call which signs that message for you. Scripts will never touch the keys then.

  • Even without exposing the key, and exposing signing only (no decryption), that's still enough to do tremendous damage (especially if the page stays open for a while). For example, signing-only is enough to carry out a transparent man-in-the-middle attack on a TLS handshake (assuming you use a DH/ECDH key exchange, and who doesn't these days?) because all of the "prove you have the private key" steps boil down to "sign some arbitrary bytes". Such an API would need to be restricted (by sites, and ideally by keys per site), and require explicit user interaction each time those limits are relaxed.
    – CBHacking
    May 21 at 11:34
  • wow! quite a communication lag. I almost finished my phd in the meantime ;-) I agree of course. However I'd argue it's still much-much better than exposing the keys. The attacker must maintain it's backdoor to exploit the signing, which is quite a burden, sometimes impossible. I agree on that successful API call needs user interaction. It's trivial, if we value our keys in any ways. However even in case of some broken design where the API allows automatic signing, the user could be notified which is huge plus compared to plain stolen priv keys.
    – goteguru
    May 22 at 12:46
  • 1
    Sure, it depends on the use case. For TLS server it's bad for a little while but not continuously, but if the attacker steals credentials or other sensitive data during that window that could become an ongoing problem. For S/MIME or TLS client it lets you take a few actions (sign some messages or log into some servers) but again, damage is limited to what you can achieve in that time (which might include a long-term foothold, e.g. if you send a message saying "I'm rotating out this key tomorrow, new cert attached"). Sign with a CA private key and you could create SO many problems, though...
    – CBHacking
    May 22 at 23:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.