How to Create a Digital Signing Solution with Only JavaScript

April 16, 2009

It is sometimes required to have the user sign a text in order to certify that he is the one who has done the operation. For example, in an e-banking software, the user might have to sign a text describing the transaction (“Transfer 300 dollars to IBAN xxxxxxxxx”), or sign a request for a governmental eService. This could be achieved by a java-applet, but as JRE owners are not a majority, it is preferable to use other ways.

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, the solution below wouldn’t work.

Also, note that this uses PKCS7 (java developers: use bouncy castle to verify it), instead of the XAdES standard. Internet Explorer has support for XAdES, but FireFox doesn’t.

Let’s see a simple HTML page that should sign a given text:


<script src="sign.js" type="text/javascript"></script>

<input id="text" type="text" />
<input onclick="signDigest(document.getElementById('text').value);" type="button" value="Sign" />

and then the JavaScript itself:

(Update: the code is now available on GitHub – js-signer)


function signDigest(text)
{
if(window.event)
window.event.cancelBubble = true;

var dest = sign(text); //TODO
alert(dest);
return dest;
}

// CAPICOM constants
var CAPICOM_STORE_OPEN_READ_ONLY = 0;
var CAPICOM_CURRENT_USER_STORE = 2;
var CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
var CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY = 6;
var CAPICOM_CERTIFICATE_FIND_TIME_VALID = 9;
var CAPICOM_CERTIFICATE_FIND_KEY_USAGE = 12;
var CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE = 0x00000080;
var CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
var CAPICOM_INFO_SUBJECT_SIMPLE_NAME = 0;
var CAPICOM_ENCODE_BASE64 = 0;
var CAPICOM_E_CANCELLED = -2138568446;
var CERT_KEY_SPEC_PROP_ID = 6;

function IsCAPICOMInstalled()
{
if(typeof(oCAPICOM) == "object")
{
if( (oCAPICOM.object != null) )
{
// We found CAPICOM!
return true;
}
}
}

function FindCertificateByHash()
{

try
{
// instantiate the CAPICOM objects
var MyStore = new ActiveXObject("CAPICOM.Store");
// open the current users personal certificate store
MyStore.Open(CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY);

// find all of the certificates that have the specified hash
var FilteredCertificates = MyStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, strUserCertigicateThumbprint);

var Signer = new ActiveXObject("CAPICOM.Signer");
Signer.Certificate = FilteredCertificates.Item(1);
return Signer;

// Clean Up
MyStore = null;
FilteredCertificates = null;
}
catch (e)
{
if (e.number != CAPICOM_E_CANCELLED)
{
return new ActiveXObject("CAPICOM.Signer");
}
}
}

function sign(src)
{
if(window.crypto &amp;amp;&amp;amp; window.crypto.signText)
return sign_NS(src);

return sign_IE(src);
}

function sign_NS(src)
{
var s = crypto.signText(src, "ask" );
return s;
}

function sign_IE(src)
{
try
{
// instantiate the CAPICOM objects
var SignedData = new ActiveXObject("CAPICOM.SignedData");
var TimeAttribute = new ActiveXObject("CAPICOM.Attribute");

// Set the data that we want to sign
SignedData.Content = src;
var Signer = FindCertificateByHash();

// Set the time in which we are applying the signature
var Today = new Date();
TimeAttribute.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
TimeAttribute.Value = Today.getVarDate();
Today = null;
Signer.AuthenticatedAttributes.Add(TimeAttribute);

// Do the Sign operation
var szSignature = SignedData.Sign(Signer, true, CAPICOM_ENCODE_BASE64);
return szSignature;
}
catch (e)
{
if (e.number != CAPICOM_E_CANCELLED)
{
alert("An error occurred when attempting to sign the content, the errot was: " + e.description);
}
}
return "";
}

And that should do the stuff – the signed text can be sent to the server, where it can be verified.

P.S. One important note when verifying afterward – Internet Explorer uses UnicodeLittleUnmarked (UTF-16LE) to encode the signed data, before signing it. So when verifying, use this encoding.

If you find the content interesting, you can subscribe and get updates


 

87 Responses to “How to Create a Digital Signing Solution with Only JavaScript”

  1. Can we see a demo of this?

  2. Well, it’s pretty much all in the code above – just copy-paste it in an .html file and you have the demo. But have in mind that you must have a real signature, otherwise browsers give errors.

  3. IE gives this error: “An error occurred when attempting to sign the content, the error was: Automation server can’t create object”

    Ever seen such? :)

  4. Yes. In order to sign successfully (with both IE and Firefox) you need a installed smart card with the digital signature. Self-signed certificates can’t be used with the browsers to sign content. (don’t ask me why :) )

  5. Hi, this jscript is encrypting some given text “Hello” using CAPICOM sertificate?? Ok, so if this is true i would like to get public Key from sertificate, and later use this public key to verify authetntication of used sertificate for encryption(i will encrypt the same text “Hello” but this time with public key and compare both encriptions). Is there any chance for that???

    Thanks

  6. I didn’t quite get your idea, but getting the public key from the encrypted message will be a server-side action, about which I will blog tomorrow (stay tuned). Then you can use it in whatever way you need.

  7. [...] to obtain signer’s details from a JavaScript signed data By bozhobg In a previous post I described how to sign data with only javascript. Now, this data should be used on the server side [...]

  8. Check this out – http://bozhobg.wordpress.com/2009/07/02/how-to-obtain-signers-details-from-a-javascript-signed-data/

  9. Hi,

    Thanks for your quick replay. My question was how to get public key from CAPICOM certificate.Later use that key to decrypt signed(encrypted) text, and make comparison between original and decrypted text, wich should have some function like verification.

    P.S is there any chance to convert your Java code from your newest blog to C#?

    Thanks

  10. Well, I don’t have enough experience with C# to be able to do so – furthermore, I’m not even sure bouncy castle have C# libraries, so you have to ‘translate’ it yourself, and find the appropriate libraries :)

  11. hi me again :)

    I can’t understand why on some PCs i am able to get Certificate and sign text and on the other PCs i am get error (Error in reading DLL)????

    when i was Debuging I found that this error occurs in the next two lines.

    var SignedData = new ActiveXObject(“CAPICOM.SignedData”);
    var TimeAttribute = new ActiveXObject(“CAPICOM.Attribute”);

    Thanks for your time and previous responses.

  12. I forget to say that all PCs in my network have certificate by same Issuer.

  13. Hm, that would probably be due to unsuccessfully installed smart-card software (Charismatics, for instance). Check the installation procedure from the signature vendor.

  14. Thanks i instaled CAPICOM on all PC’s where i was not able to get theirs certificate, and that solves my problem, now it’s working exelent.
    Thanks again for your help.

  15. This is good but i need only Secure email signature from etoken can u tell me the javascript code for that

  16. Whether it is SmartCard, eToken or self-signed certificate , it doesn’t matter, as long as the browser is set-up to locate them.

  17. Hi.

    Thanks for this valuable article.I wanted to know the signed output length of your code.I am getting morethen 3000 char ,even for a 15 char input.

    Thanks and regards..

    Ramba

  18. Yes, this is normal. The whole certificate data is encoded in base64, so it’s fine.

  19. Thank you for your response.I wanted to convert this output into pdf417 barcode ,2D. Pdf417 is supproting upto 1800 ascii character only.

    Is there any way to compress the output to reduce the number of characters?.Or please suggest alternate for capicom ,to sign at client side.

    Thanks and Regards.
    Ramba.

  20. What information should the barcode contain?
    You can extract whichever part of the PKCS7 you wish – check this post: http://bozhobg.wordpress.com/2009/07/02/how-to-obtain-signers-details-from-a-javascript-signed-data/

  21. Thank you for your reply.

    The barcode should contain the signature.ie SignedData.Sign methods output.I am implementing in asp.net application.The content of the barcode should be used for signature verification in future.

    Regards

    Ramba

  22. Well, then extract the publicKey and put it in the barcode. Should suffice.
    But the PKCS7 contains much more information, hence the big size.

  23. Thank you,

    I will do in that way.

    Regards,

    Ramba

  24. Thank You,

    I will do based on your suggession..

    Regards,

    Ramba

  25. Thanks you for Reply
    I created code for reading etoken code is working fine on local host but when i access page from IIS this is not working What i have to do for that.

  26. “Whether it is SmartCard, eToken or self-signed certificate , it doesn’t matter, as long as the browser is set-up to locate them.”
    How to set upi IE to locate SmartCard so that user can enter pin and then use cert in this js

  27. It depends on the smart card software. It should include detailed manual on how to enable it on each browser.

  28. [...] How to create a digital signing solution with only JavaScript [...]

  29. You are missing “strUserCertigicateThumbprint”, where is this created? What should go here?

  30. Thanks a lot Bozho.

    >Could you copy-paste your question at >http://techblog.bozho.net – I’m not sure how this old >version of the blog will continue to live, so it’d be better >if I answer you on the other one.

    The question I posted on the other blog:
    bozhobg,
    Hi.
    I tried this code and works perfectly. I was searching for the same results and the code looks great.
    The problem is the signer.sign result. The signature happens to be @ 2292 bytes. I think it is too long. We are used to hash the data with SHA1 (40 bytes) and sign with RSA 1024 key. The resulting signature is 128 bytes (172 after BASE64).
    Can you please tell me how to resolve this issue so that the sign is 172 bytes long (BASE-64). This is the only thing that is holding us to use the code.
    Thank you for this awesome post.

    Update:
    I studied on another post about the PKCS#7 format:
    http://www.jensign.com/JavaScience/sigview/

    Can we extract the last 128 bits of the PKCS#7 output (from the CAPICOM sign method) to get only the digital signature?

    Thank you again.

  31. @Nitin Nanivadekar Well, you can hash the hash of the result either through javascript (http://bit.ly/9cgzTu), or send it to the server and hash it there (using MessageDigest)

  32. Can we extract the last 128 bits of the PKCS#7 output (from the CAPICOM sign method) to get only the digital signature?

  33. [...] a previous post I described how to sign data with only javascript. Now, this data should be used on the server side [...]

  34. Your JS to sign is good.
    I read also “How to obtain signer’s details from a JavaScript signed data” and I’ve seen that this operation is done on a server and is Java. What I need is to verify a signed message given back to me on my computer. Si I need a JS to obtain signer’s details, Is it possible?

  35. I don’t know. But you can send it to the server to obtain the details, and send the details back (with ajax, perhaps)

  36. I will try calling CAPICOM activex from JS.
    Thanks

  37. This looks good for FireFox and IE.
    But will it work in Chrome or Safari?
    I don’t see support there for crypto.signText().

  38. Alas it won’t work there. If you want a completely portable signing solution, you’ll need a Java applet. But it has its drawbacks.

  39. Hello,
    Thanks again for a great app.
    The app runs well where on a developer machine where we have installed Visual Studio.
    But when we try to run the app from a machine without a Visual Studio, we get the error: “Automation Server Can’t create Object”.
    Do we need to install some other application on the client machine to remove this error? or what configuration change we need so that the application works properly on any client?

  40. Update:
    I tried to run the SDK at http://www.microsoft.com/downloads/en/confirmation.aspx?FamilyId=860EE43A-A843-462F-ABB5-FF88EA5896F6&displaylang=en to install the SDK.
    But the error “Automation Server Can’t create Object” is still showing up.
    Please help.

  41. Update:
    It worked. WOW.
    The solution is to register capicom.dll on the client machine.

    Thanks Bozho. Love…

  42. gr8!!
    code worked fine for me.

    but i have dought. what that IsCAPICOMInstalled() method does.

  43. Bozho,

    The code is working fine in 32 bit Server OS. But there are issues in running in CAPICOM in 64 bit OS.
    Please, can you suggest changes in the code to run in say a .Net with native .Net code instead of COM based code?

    Thank you. I must again say this is a great utility.

  44. I have no idea about 64 bit.. If you find a way ‘through’, please share.

  45. We need to develop our own CAPICOM in order to run this Javascript code on a X64 machine.
    Please share your knowledge if someone is already working on this.

  46. Hi,
    I have started looking at crypt32.dll for possible replacement of CAPICOM.
    Can you tell me if your Javascript code will work with crypt32 if we just replace procedure calls to match crypt32 function names to do the same thing as in CAPICOM?

  47. I don’t know. Give it a try.

  48. Nitin,

    This code will work fine on X64 bit machine. you need to install CAPICOM on that machine.

  49. On May 19, you replied:
    @Nitin Nanivadekar Well, you can hash the hash of the result either through javascript (http://bit.ly/9cgzTu), or send it to the server and hash it there (using MessageDigest)

    This went over my head.
    I have a requirement of extracting only the 172 characters of the digital signature (Base64 encoded) out of about 4164 characters that result from the code – var szSignature = SignedData.Sign(Signer, true, CAPICOM_ENCODE_BASE64);

    Also, szSignature is getting some newline characters from the result.
    Admin, Can you please suggest how to get the right digital signature only?
    is there any way, like extracting the last 172 characters from szSignature?

  50. I’m sorry for not being helpful, but I wrote this code 1.5 years ago and right now I’m busy to look it again and remember what’s being done.

  51. Great post!!
    I was looking for a way to implement this! Now, after I’ve done this, is there a way to verify the certificate on the server side using PHP?
    Thanks!

  52. Almost certainly there is a way, but I don’t know – haven’t done PHP for a while

  53. Hi Bozho.

    1. Can this code support the much secured SHA2 or 2048 bit keys?

    2. Have you come across a way to read the public key from the USB based key store?

  54. I don’t know, I haven’t used this code for 2 years now. The USB based key-store – it should be the browser’s responsibility to load the keys. If the browser presents the keys, then the above should work.

  55. Hello! Well it`s been a year since last comment, but let`s try.
    I`m desperately looking for a way to sing a File from browser using JS only (well maybe some severside php to put it somewhere on the server).

    The best I can think of is something like emulation of real process.

    User uploads file, we with serverside scripts (e.g. php) count its hash than user signs it.
    What are the pros and cons I can`t see, and I`ll gladly try some other methods.

  56. For files we used Java applets, to allow signing on the client. With JS it seems that a server should participate and send the hash for signing. This is, strictly speaking, not secure, because someone may temper the file during the process, but I think it’s good enough.

  57. I am using this code and I commented two lines. //if(window.crypto &amp;&amp; window.crypto.signText)
    // return sign_NS(src_message); Because I am using IE. I have executed at developemnt environment. It’s fine it’s working and giving certificates to choose and then it gives hash of the given string. but after deploying it is giving error “An eeror occured when attempting to sign the content, the errort Automation server can’t create object”

  58. This code was running excellent when there is visual studio environment in the machine. but in client machine its not working fine and saying the automatic server can’t create object. I have installed capicom dll in the client system also. Help me out

  59. Thank you Bozho for such useful sample code.

    We are actually trying to sign a .pdf file, rather than just text. do you know if there is a way to read a file from the file system (from the browser) and assign it to SignedData.Content?

    Also, your code seems to correct for it, but I am having the same problem as a user above. this line:

    var FilteredCertificates = MyStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, strUserCertigicateThumbprint);

    Throws the following error:
    “‘strUserCertigicateThumbprint’ is undefined”

    can we just pass null for this? where did you define it?

    thank you
    Harvey

  60. Hi,

    Unfortunately, I did that years ago, and I don’t remember the details.

    You can’t sign a PDF, that’s for sure. But you may get a hash of the PDF and sign that – should work, I guess.

  61. Hi,

    Can i use Sha2 encryption?

    How can i validate the certificate is up to date?

    thanks.

  62. Hi Bozho

    I know I made ​​the code a few years ago, but maybe you can help me. I could adjust your code to only read data from the client’s digital certificate?

    I’d like to read this data and use them to control a login page of a website.

    Homero

  63. Well, simply use an identifier from the certificate you obtained and store it in the db, then check it and perform the login.

  64. Hi Bozho

    Tanks.:-) Is it, but you have an example code? For example, where in your code in this post I could take the value of the certificate, eg the name or subject or a particular field?

    I’m “struggling” to adjust the code of the post, but have not figured out how to determine this with Capicom. :-)

    The idea is exactly that, I would read a value from the database and compare with the value on the digital certificate to allow access to certain pages of the site.

    All help is welcome. :-)

    Homero

  65. Hello Dear,

    I want to attached digital certificate with my web page.
    but don’t find anything. I need to decrypt that certificate from token USB device and have to attached with my webpage.

    I had also saw one application which is in ASP.NET where One popup window that come from click on one button called “Select Certificate” but doesnt able to make it in php

    Your Above explain concept I have read properly but it doesnt work when I copy and paste in html.

    Want to ask that CAPICOM library will be a file or it will automatically get its function.

    Please help me here. I had make full R N D in that but didnt find any thing.

  66. can anyone will help me out here.

  67. [...] http://techblog.bozho.net/?p=37 (How to Create a Digital Signing Solution with Only JavaScript) http://techblog.bozho.net/?p=87 [...]

  68. [...] 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 [...]

  69. Greate Work:) This Code is Working Fine for 32bit Os … Have u Any Idea for 64 bit Os…Pls anybody knows about 64 bit please Share:)

  70. It should work on 64 as well, I’ve been using it on such machines

  71. Hi! I understand this is somewhat off-topic but I had to
    ask. Does running a well-established website like yours require a large amount of work?
    I’m completely new to running a blog but I do write in my journal every day.

    I’d like to start a blog so I can easily share my experience
    and views online. Please let me know if you have any kind of ideas or tips for brand new aspiring
    blog owners. Thankyou!

  72. Varieties include traditional metal, gold braces, and clear
    plastic type kinds. Your non verbal movements say much more
    about how you come to feel than your words
    do. We have found that in grading our deals, we were making the best use of our times working on deals that
    had a high chance of closing.

    Also visit my blog; women leans

  73. Have a supply of disposable applicators so clients will always
    have what is needed to sample products without cross contamination from hands,
    eyes, lips, etc. It is right to be informed of the products that we use and consume on our bodies.
    At this online shopping site, you will get variety of cosmetic products from Inglot brand.

    The European Commission on Endocrine Disruption disclosed that there is strong evidence of its effect as a human disruptor.

    A Butulanium bacterium produces seven types of poisons that operate in a similar way.
    00 A light emulsifying kit enriched with effective plant extracts to lighten the color of the
    skin and improve the texture without affecting moisture level of the skin. Clientele is that the creation of an innovative mind that belongs to Pat Riley.

    It’s the eyeshadows that most demonstrate the lack of color distribution. Photos and important information can be found on the official Facebook page.
    Below are a few suggestions that will help you find the best cosmetics for your sensitive skin. Or do you think they are
    going to opt to use the cheapest ingredients available on the market to ensure optimal
    profit for their business. – Hair care products
    accounted for more than 25% (expected) of the total cosmetics &
    personal care market in 2007. Epsom salt soak for infected cuts:
    One cup of unboiled warm water with two table
    spoons of Epsom salts plain soak for twenty minutes twice a day till infection is gone.
    But it is always crucial to consider what products you are selling; your complete success depends on proper
    selection and adequate know how. Often online stores
    provide great discounts on products in order to be competitive.

  74. I really like what you guys are usually up too.

    This type of clever work and exposure! Keep up the excellent works guys
    I’ve added you guys to my personal blogroll.

  75. We all face high electric bills during those long summer months and wish there
    was a way to reduce them. I can see the white sand
    beaches, feel the warm ocean water, and smell the fragrant breeze.
    The second quote in the first image is also very important.

    Visit my blog :: powerbank

  76. my application is in ASP.NET and i want to provide login using digital certificate.
    I want to read digital certificate info and store it in database then i have to provide login with digital certificate.I am trying to get certificate info but i coundnt using java-script. please help

  77. Thanks for the a new challenge you have exposed in your text.
    One thing I’d prefer to discuss is that FSBO human relationships are built
    eventually. By presenting yourself to owners the first weekend break their FSBO is announced, prior to masses start out calling on Thursday, you create
    a good network. By mailing them resources, educational materials,
    free reports, and forms, you become an ally. If you take a
    personal affinity for them plus their circumstance, you make a solid
    link that, oftentimes, pays off once the owners opt with a realtor they know in addition to trust — preferably
    you.

    my blog: promoting gold

  78. Thank you for some other informative web site.

    Where else may just I get that type off info written in such an ideal method?
    I’ve a challenge that I am just now operating on, annd I’ve bedn at the look out for such info.

  79. Of course, if you want to build teamwork, you will definitely want to practice together.
    So, strap on all your paintball load and gear up those paintball
    guns! Work on defensive and offensive strategies, code words,
    “what-if” scenarios, and more. Learn from the opposition along
    with your personal teammates. Carefully discover other paintball athletes to develop new and successful approaches for upcoming game titles.
    Does the opposite team discuss more than your crew does?
    Do they really appear to be much more arranged? Focusing on how your foes come together may help increase your team’s overall performance.
    Take a look at your opponents paintball gear and see if your team
    is lacking in that area. This will greatly result your
    game play

    Here is my blog post :: paintball gun (http://forum.bakujug.com/)

  80. My relatives every time say that I am killing my time here at
    web, but I know I am getting familiarity all the
    time by reading such nice posts.

    Feel free to visit my web blog :: free tarot readings online

  81. This is my first time pay a quick visit at here and i am truly happy
    to read all at single place.

  82. This text is worth everyone’s attention. When can I find out more?

    Look into my web blog Télécharger GTA 5

  83. Howdy this is somewhat of off topic but I was wanting to know if
    blogs use WYSIWYG editors or if you have to manually
    code with HTML. I’m starting a blog soon but have no coding expertise so I wanted to get
    advice from someone with experience. Any help would be
    greatly appreciated!

  84. Since the software is downloaded and installed
    on your home PC, you can access it only from your own computer.
    By choosing this set, you will always have a tiny piece of Las Vegas Nevada to yourself.

    The Prison Tycoon series is just awful, I know it
    sounds like it might be fun but believe me it isn’t.

  85. So a search by a new visitor for a product that Amazon doesnt sellwhich results in a sale through the merchantmeans
    that Amazon has acquired a new customer. While not usually endorsed
    by the product manufacturer these hacks should not be confused with more nefarious computer hacking.
    Make sure your photographer understands your budget.

  86. hi!,I like your writing so a lot! share we communicate extra approximately your article on AOL?
    I need an expert in this space to unravel my problem.
    Maybe that’s you! Taking a look ahead to peer you.

  87. This is the best fotografi matrimonio napoli in this world.
    Mainly it covers the actual Microsoft windows and also the Microsof company servers.
    Children and grandchildren can be shown the photographs of the wedding ceremony.

Leave a Reply