Thursday, September 1. 2016
When the blog was started a three post series was published about digital signature in the web. At that time I recommended the use of applets in order to access local certificates. Nowadays applets are an old fashion technology and, even worse, it is being deprecated or, at least, they are not recommended by all the major browsers. So applets are out of the game and I advise against them. In more recent times the blog dealt with the new Web Cryptography API, a W3C standard which, I thought, was the long awaited technology to cover digital singing in the web. Nevertheless the new API does not integrate this specific use-case due to some reasons analyzed previously in the blog (mainly because the internal browser certificates and keys are not exposed to the API). So, here we are again, signature in the web is a hard and tough subject which (in the year 2016) has no direct solution. There is no clear API or technology that fits to the case. In my humble opinion this is an extremely strange situation produced by the enormous indolence of all the players in the game (I suppose no one is interested in the case).
Today's entry is my little contribution to the subject in the current messy environment. Remember that there is no clear solution and, I think, this situation will not last forever and will improve shortly. But, in the meantime, a temporary solution is needed because applets are very problematic. During the last weeks I have been thinking about the current alternatives and exploring some of them. My final thoughts were summarized in only two ideas:
Implementing a plug-in or extension for the major browsers. You know that firefox 48 is now exposing the WebExtensions, which is the try of showing the same API for extensions than chrome. For that reason I decided that exploring the implementation of a WebExtension was a good idea. The documentation of chrome offers some APIs to access to the certificates (for example platformKeys) but, as I discovered later, all those extensions are only for Chrome OS (it is curious that the signature use-case is interesting for the Google's OS but not for the others). So, again, an extension seemed a closed path (in chrome you can implement a native client but the solution is restricted to this browser and implementing an extension for every browser is a crazy idea).
The other solution is just a workaround for the messy situation. Instead of using the browser directly (the clear solution simply does not work) a local process or daemon will give the access to the certificates and will expose them to the browser using http(s). This way the browser will communicate with the local daemon using a Web Service and the access to the certificates will be centralized through the daemon. In order to make the solution viable some headers are needed in the WS (Access-Control-Allow-*), the headers to permit cross-origin HTTP requests (CORS). The general solution is described in the following diagram.
I know this idea is just a workaround. Besides it is quite laborious too, implementing a full daemon is not an easy task and it needs some thinking to make it secure and light. In this entry a simple PoC will be presented implemented in Java.
So let's start with the PoC. As it is commented above, the idea is running a local HTTP server in the client machine using a daemon (something started by the init system -windows service, rc or systemd script, Solaris SMF or whatever-). The PoC implements it using the internal HTTP server that the Java SE integrates (since version 7) and jettison library (for interchanging messages in JSON). It also re-uses the old Signer implementation used in the applet series to communicate with the real certificate repository. This way the server just handles one repo (the process does not manage two or more different certificate stores). The server is started with a configuration file (a properties file) which contains the properties for the repository (the same props used previously for each Signer implementation for the applet) and some new ones for specifying other server characteristics (port and context for the WS -the http server only listens in localhost obviously-, which domains are allowed to connect -CORS data-, the Signer implementation to use and so on). The server provides the following web services:
isInitialized: A simple method that indicates if the repository is initialized or it is closed. The method responds with some simple data about the characteristics of the certificate store besides the initialization condition.
initialize: Opens the repository with a password (maybe not needed in some repos). It also returns the characteristics of the repo.
listCertificates: Method to list all the certificates in the repository. It responds with a list of certificates with some properties for each one (subject, issuer, serial number, dates,...).
sign: Method to perform the signature. It just receives the data to sign (encoded in base64), the type of signature (JCE style, SHA1withRSA for example), the alias of the certificate to use and the password (if needed). The WS returns the signature in base64.
verify: Verification of a signature. It receives the signature (base64), the plain data to check (base64 too), the type of signature and the alias of the certificate to use. It just returns if the signature is valid or not. This operation can be executed in the browser cos it depends on the public key (WebCrypto API for example), but I included it in the daemon for simplicity.
Finally I developed a little HTML page which performs a signature and then validates it. It calls the WS methods provided to perform the process. The page just uses JQuery to communicate via JSON and the CORS headers let the browser access from the internet page to the local server.
As usual a video shows the whole process. First the daemon is started manually using the command line (configured to use Spanish eID DNIe with OpenSC in port 8000, I wanted to show a complicated environment with hardware tokens). Then the page is accessed and a simple message is prepared to be signed. As soon the Sign process is started, the page performs the initialization and a password is requested to the user. The initialize method opens the PKCS#11 module in the daemon. Then the page calls for the certificates and presents them to choose the one for signing. Once the certificate is chosen by the user the sign WS is called (in OpenDNIe no password is needed for each key). As I am using the OpenSC implementation a warning message is displayed that must be accepted by the user (this can be problematic if a real daemon with no X session was used). The signature is returned and placed in another text-area. Finally a verification is performed.
Today's entry is a simple PoC that shows a possible solution to perform digital signature in the web due to the current messy situation. The idea is counterintuitive because it uses a local process running in your system instead some new and bright web technology. But do not blame me for that, in the year 2016 there is no way to perform a signature just using web technologies (old technologies are deprecated, new ones do not care about it). You have to understand that the solution is a workaround. It solves all the issues with previous technologies and runs in any modern browser. For non pc devices (phones and tablets) the idea would work too but for sure it needs some adaptation (indeed for those devices everything is an app, so why bother about the browser). The workaround presented in the entry will be replaced by a new standard that hopefully will come in the future. You can download the NetBeans project used for the PoC from here. Please do not use the code just like it is. This is just the presentation of the idea, not any final solution. The implementation should be carefully improved in terms of security, usability and agility. Besides, it is a workaround, all the more reason for being specially meticulous in such a sensitive use-case.
Think before act! But act!
Saturday, February 14. 2015
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 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!
Thursday, September 4. 2014
Some weeks ago I decided to check the new implementation of the Web Cryptography API that was just enabled in chrome 37 beta. If you remember I talked about this standard some months ago in a quick entry and I wanted to continue in a more technical post. As soon as I started I felt that the API is quite bad documented and I did not find any example for what I wanted to check. I was trying to implement a similar solution to the one I presented in the applet series (that series implemented a signed email solution using an applet). I checked and re-checked the API and I did not find a clear method to use a certificate key (a key of one of my certificates previously imported in the browser). At first sight only two ways were admissible:
Using the importKey with some strange format or arguments.
Using another standard (apart from webcrypto-api but related) called WebCrypto Key Discovery which has a getKeyByName method.
Those options were only ideas and it was impossible to find any example or comment about what I was trying to do. All the examples over the Internet use a previous generated key (some of them export the key and re-import it to be re-used without creating another one) but no one tries to use the key of an imported certificate and, even less, a certificate / key pair hidden inside a PKCS#11 library in a crypto-device like in the last post of the Java applet series.
A bit tired after some hours trying to find answers I decided to post a question to the chromium lists and, surprisingly, PhistucK answered me saying that this use-case was not taken into account and that the WebCrypto Key Discovery API was not implemented in chromium. It was surprising, I had just not thought about that possibility, how can a webcrypto-api not consider user certificates? I suppose that I fell into that mistake because all the times I faced cryptography in a web environment the task was related with user certificates (document signing, voting events, email signing or encryption,...). I simply did not consider any other situation.
The same morning I discovered a youtube video uploaded by Inventive Designers which clarified the situation to me. Using user certificate keys is out of any specification, neither webcrypto api nor webcrypto key discovery cover that situation. I exchanged some emails with people of the company and they explained that W3C is moving forward with the webcrypto-api and there is a workshop to define next steps and goals. They have submitted a proposal for document signing and they will attend to the workshop trying to incorporate it as a new feature inside any standard. So they are pushing but, in their own words: "There is interest of other people in the WG (working group), but browser vendors are still not keen to add this feature. Depending on the outcome of the workshop this may change...". At the moment I have seen that Inventive Designers have implemented a chrome plug-in to present a proof of concept of their idea. (At first glance the plug-in only works on Mac and seems to retrieve certificates from internal system certificate store. I suppose that Mac is similar to Windows and it stores user certificates at system level. Besides I think that this implementation needs direct access to the internal private key.)
I do not know, I feel a bit depressed. I thought that the WebCryto API was the final solution for cryptography in the browser but it resulted in a big disappointment. The API covers none of the use-cases in which I have been involved in my professional life. I suppose that it has some value in other areas but it is absolutely useless in document signing. At least there are some people trying to complete the work and integrate this important feature in the standard.
Let's see what happens in the workshop!