If you usually follow the blog you already know about the Web Cryptography API, it is a new standard JavaScript API to perform cryptography operations inside the browser. I felt depressed the last time I tried to play with it, because it does not cover any of the typical scenarios I have faced in my professional life (digital signature mainly). The last months the Charles Engelke’s blog have been publishing some beautiful articles about the same subject, and I think that I have finally understood what the final goal of the API is.
Charles Engelke's last entry plays with WebCryptoAPI and X509 certificates. He parses a self-signed certificate, extracts its public key and signature and validates the latter (in a self-signed certificate the signature is signed by itself, by the private key associated with the certificate, so it is verified with its public key counterpart). In today's entry I decided to test it by myself but doing some minor changes.
A RSA key pair and a certificate were created using openssl.
$ openssl genrsa -des3 -out server.key 2048
$ openssl req -new -key server.key -out server.csr -x509 -subj "/C=ES/L=Madrid/O=Home/CN=TestSign" -days 7300
Finally I exported the key pair and the certificate to a PKCS12 file.
$ cat server.key server.csr > server.pem
$ openssl pkcs12 -export -in server.pem -out server.pkcs12 -name testsign
In order to test that everything was working, a simple Sign.java class was implemented to perform a signature using the previously created key pair and then validating it.
$ java Sign "sample text"
Singature:U72gD6t14VpCqKitUTEcBfa0TqXte/IPFLOF0wms+HfU+eTrEDQwZLZtZ0ju988JY/JsGElN9gxM
apEKFnjiaS2O0qXMGrSSALgDKbGkSlvishFXysfYrWcYEn2/2mfuI3i9MYFqu2LgOTr1GC/jHqFm
W0UW5NuRJCDaFEBbQBzedcuXuzKNcu18uFvUV2zJyHliuViU7L4m12vK9reFUTj7ghZBml62Lpxl
g6CgjDdvBqy7tBh17k3OjHfINZiHLRb5ZA+3+YJRBAA2yOjUgaCWuGlwtqbLlWiuzxHF3XQxV/yh
ad5Xw0RHdANLhiJixXuOTRbzEdLYHhBU7iL0Cw==
Is signature OK? true
The class just loads the certificate and the key pair from the PKCS12 store and signs the text passed as the first argument. It shows the signature (in BASE64) and verifies it.
At this point I decided to change a bit what Charles was doing, instead of verifying the signature of the self-signed cert I was going to verify any signature (it is almost the same). So I collected all the JS code that Charles presented in the entry and prepared a static HTML page which is included at the end of the entry.
As you can see it is a simple page that places the certificate in PEM format, the text signed previously with the Java command and the resulting signature in three different text areas. If you have a browser that supports the WebCryptoAPI the signature can be verified clicking the button (following the notes from Engelke's blog the certificate is parsed to recover the public key and with it the signature is verified just using JavaScript).
So now I understand a bit more what this API is about. Right now the standard just implements the cryptographic operations in raw. All the operations are done using direct access to the keys (for example in this entry the public key is read from the certificate and then imported into the crypto object to be used). Therefore for the moment no hardware tokens can be used. Second thing I have clear now, the standard does not know anything about what a certificate is. The Engelke's code just parses a certificate (ASN.1 format) manually in order to obtain the real bits of its public key and it does not check certificate dates or the trusted chain (signature verification just performs the mathematical algorithm). Instead of verifying the signature a real signature could have been done but, as the private key is needed, the real bits of the private key should have been provided to the JS code (in another textarea for example). In other words, WebCryptoAPI can sign anything, but the RSA private key is needed to do that and, at this moment, there is no way to access to internal X509 user certificates and their associates keys (the private key should be passed to JavaScript directly).
As a result of this little PoC the WebCryptoAPI needs two things in order to properly handle with the signature use-case:
The API should offer operations to handle keys in hardware tokens (PKCS#11 or similar).
The API should provide methods to manage certificates (Engelke's methods are wonderful but you know, this is an API, please do it nicely) and to access the internal (browser) user certificate store (maybe it could be just incorporated as another token). Obviously this is a risky operation and some confirmation from the user should be requested. But this is not a strange behavior, exactly the same thing is done when mic or camera are requested in WebRTC or when a site requires a user certificate to log the user in. With those methods the JS code could recover the internal certificate and the private and public key associated with it.
I think that, more or less, both requests are already in mind of the W3C group as the report of the workshop states. Hardware token are specially important because the second point depends on it (nowadays a personal certificate is always inside a secure hardware token, for example a lot of national eIDs work this way). The second point is exactly what people of Inventive Designers demanded in their presentation.
Finally in order to present a more workable PoC I prepared a little restful WS application that has the self-signed certificate inside and can sign and verify using WS in the server. The idea is you can sign any text and verify it using internal (using WebCryptoAPI in a capable browser) or external method (using WS and executing in the server).
The following video shows the little application. Using the firefox developer edition (iceweasel in Jessie is version 31.4 and does not support the API yet) I access the main page. First the certificate is requested to the server. Then some sample text is signed and verified externally. When the verification is internally done, the browser parses the certificate, obtains the public key and verifies the signature using the WebCryptoAPI. If the text is modified but not signed (the previous signature is still in the textarea) both validation fails.
Here you can download the maven project for the application.
This entry is a little test I did just to understand what the WebCryptoAPI can and cannot do. After I read the interesting entries about the same subject done by Charles Engelke I finally understood the idea behind the API. It presents methods for typical cryptographic operations in a basic raw mode. Until now there are no certificates or hardware tokens and, therefore, direct access to real key bits are needed. So, in my opinion, this API is just an entry point to be completed by a second one or an extension of this one.
Stay tuned for news about the WebCryptoAPI!
Example page
Comments