Using browser's certificate (private key) to sign some string in javascript - javascript

My users have some certificates (private keys) installed in their web browser. These certificates are used by the browser to authenticate the user on certain third party websites.
I would like to sign some string using one of the private keys, when the user uses/visits my website. Is there any JavaScript API or function, which would enable to do this?

Short answer, you can't sign a string delivered through the web browser using Java Script and a Client certificate from the end user.
In your case the user certificates and keys are used for TLS Client Authentication:
During the TLS Handshake the Server will request the browser to present TLS Client certificate.
The browser will pick a suitable Client Certificate and establish the TLS connection.
Once done, the server will deliver the content: HTML , JS, Images...
The browser will render the page with all the elements.
The browser has an API to access the client certificates and keys but this is not exposed to the Java Script engine.

Related

Download client over ssl but connect to arbitrary IP

In browsers, is it possible to request javascript for a web-client over https, but have said client connect with a websocket to an IP either:
without ssl
with a self-signed certificate (without previously adding the certificate to the browser)
From what i read, it simply isn't. Mixed content is forbidden, and self-signed certs are not accepted, unless the user goes through a weird and dangerous looking menu, to manually accept the certificate in the browser. It's not like the typical user has the qualification to check a certificate anyways.
This would directly imply, that for this case, encryption cannot be used at all, sadly.
Isn't there something i overlooked? If the websocket connection wasn't over ssl, the client could even just encrypt itself, inside a non-ssl connection. The server it's connecting to won't have a certificate from a CA, it typically won't even have a domain.
Edit: some background
The desired situation is as follows:
a user enters a website, and gets served a client via a secure connection (this is from a static domain, so having a certificate from a CA is no problem here. However, using https apparently disallows non-ssl-connections from that site, and the client accordingly).
the client then opens a websocket connection to a server IP, which may arbitrarily vary (can even be multiple servers at the same time), and typically has no domain. For this, i can only come up with a few scenarios:
no ssl (forbidden, mixed content)
self-signed certificate, preferably the client would get the public key from the main domain, and have that pinned (self-signed produces warnings, and users can't really be required to manually install certificates just for this)
Some CA offers free and automated certificates for IPs, which we can depend on, and just generate new certificates whenever necessary, without any human action needed (i didn't consider this before, because i simply didn't think any CA would offer such a thing. Maybe there is, but so far, i've not encountered any)

Is there a way to detect if the certificate is invalid on the client side?

I am the owner of a website on an intranet and I want to reject users with invalid certificate, (for instance if a user X does not have the dedicated certificate installed on his machine he will not be allowed to access my website) :
Is there a way to detect (with javascript) if the certificate is invalid on the client side ?
What you are trying to do is fundamentally incorrect. The certificate is requested from the client to the server and the server sends its public key. A session key is then created on the client side to setup the asymm encryption.
The certificate on the web server must be signed by a trusted CA (this can be added to the client side as well). Basically the client has no control over which certificate it uses, the server will determine that.

This solution is safe to access to user's private certificate on a web with a webSoket communication?

We are developing a web page that use https protocol (two way).
We need to access to the private certificates of the user, because we need sign documents by the user's certificate, so we developed a Java application that communicate with the web by a websoket.
This application will call with a protocol call since the web (same that when you open a pdf on Acrobat Reader from a browser).
So we have to be sure that our web is calling to the native application(only our web). We want develop a system to be sure of that. Our idea:
Send a public key, a signed token by the server's private certificate and a symmetric key (to encrypt websocket communications) to the native application.
Next, we will Check in the native application that the token it is OK with a web service to the server.
After, we will have to open the websocket between the native app and the web, and send the signed document by the native app by this way.
Then sent document to the server.
Is this implementation safe? We will be safe of a man in the middle?
Any suggestion about this solution will be wellcome, because I don't see any weakness but I am not an expert on security.
I know other solutions for this problem, like applets, JavaFX or native messages on Chrome, but I only want to know if these solution is safe.
Thanks to all in advance and sorry if my english isn't the best :P,
I see the following issues
Send a public key and a signed token by the server's private certificate to the native application.
You are calling a local app by protocol. For example mylocalapp://sign?securitytoken=.... You do not control which application is installed on local PC to respond to mylocalapp://. The browser shows an ugly warning because you are leaving the secure environment. An attacker could have replaced the default app, simulate the flow and get all signed documents.
2.Next, we will Check in the native application that the token it is OK with a web service to the server.
To verify identity of server and avoid a ManInTheMiddel attach you need also to set a trustore for your application with the server certificate
Your server needs also to verify identity of client. Are you planning to use TLS two ways also?
After, we will have to open the websocket between the native app and the web, and send the signed document by the native app by this way.
You do not need a websocket. Simply use a URL connection to download and upload the documents.
This solution was used by Spanish ministry of economy when chrome decided to cut the NPAPI support and signature applets began to fail. Now, they have rebuilt the system in this way
Install a local Java application on the user's PC. The application listens on a port as, for example 5678
In your page, javascript connects to the application in the form http://127.0.0.1:5678/sign and sends the data to sign.
The application is local and has no trouble using the operating system keystore, which includes drivers PKCS#11. Perform digital signature and sends the result to the server
The javascript of the page periodically query the result and retrieves it when ready
The security problem is basically the same, but install a server in localhost is harder than replace the local default app.
The solution is called #firma, I guess you probably know it. It is opensource, you can use it

Is it possible to generate a SSL certificate in the browser?

For an administration interface we want to implement client authentication with SSL. The idea is that during the registration process every user generates a SSL certificate, which is registered in the browser and used for authenticating the client to the server. It is important that the private key never leaves the client. Hence it is no solution to generate the certificate on the server and send it to the client.
Is it possible to generate a SSL cert in the browser (e.g. IE 9+, Firefox 12+, Chrome) using JavaScript? Is it possible to register a certificate?
You can't really generate a certificate in the browser, but you can generate a certificate request (or equivalent) in the browser: the key-pair is generated within the browser and the private key never leaves it.
(Note that if you generated a certificate directly within the browser, it would at best be self-signed, since the CA wouldn't give you its private key. That's why you only get to have a certificate-request, since there's little demand for generating self-signed certificates. I think there's a Firefox extension that could do it, though.)
The certificate request is sent to the server, but the format depends on the browser and the method used. What you'll get on the server side is the public key, it's up to the service you implement to turn it into a certificate (unless you use an existing service of course). You can find more details about this in this answer.
Once the certificate is generated on the server, it can be re-imported back to be associated with the private key.

How to protect a private REST API in an AJAX app

I know that there are many similar questions posted, but none of them refers to an HTML/javascript app where the user can access the code.
I have a private REST API written in nodejs. It is private because its only purpose is to server my HTML5 clients apps (Chrome app and Adobe Air app). So an API key is not a good solution since any user can see the javascript code.
I want to avoid bots creating accounts on my server and consuming my resources.
Is there any way to acomplish this?
An API key is a decent solution especially if you require constraints on the API key's request origin; consider that you should only accept an API key if the originating web request comes from an authorized source, such as your private domain. If a web request comes from an unauthorized domain, you could simply deny processing the request.
You can improve the security of this mechanism by utilizing a specialized encoding scheme, such as a hash-based message authentication code (HMAC). The following resource explains this mechanism clearly:
http://cloud.dzone.com/news/using-api-keys-effectively
What you want to do is employ mutually-authenticated SSL, so that your server will only accept incoming connections from your app and your app will only communicate with your server.
Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. If you're using Android, you can use the keytool included with the Android SDK for this purpose; if you're using another app platform, similar tools exist for them as well. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource (keytool will generate this as well). Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.
If someone/something other than your app attempts to connect to your server, the SSL connection will not be created, as the server will reject incoming SSL connections that do not present the client certificate that you have included in your app.
A step-by-step for this is a much longer answer than is warranted here. I would suggest doing this in stages as there are resources on the web about how to deal with self-signed SSL certificate in Android (I'm not as familiar with how to do this on other mobile platforms), both server and client side. There is also a complete walk-through in my book, Application Security for the Android Platform, published by O'Reilly.

Categories

Resources