6

I understand PKI well from a conceptual point of view - i.e. private keys/public keys - the math behind them, use of hash & encryption to sign a certificate, Digital Signing of Transactions or Documents etc. I have also worked on projects where openssl C libraries were used with certs for securing communication and authentication. I am also extremely familiar with openssl command line tools.

However, I have very little experience with webbased PKI projects & hence I am trying to design and code a personal project for this.

The requirements

(This is a learning project - This is never going to be used in a bank)

This is the website for a bank. All Internet Banking users are allowed use any signing certificate issued by a few known CAs (verisign, Thawte, entrust etc). The Bank is not responsible for procuring certificates for the user. The user logs into the bank site with his userid/password etc. He has access to most parts of his account. However, when the user wants to do a transaction - like transferring money to different account - the bank wants him to sign the transaction with a certificate.

The design

When user choses "Transfer" option - the website throws up a form where there are 3 entries - "Transfer To" account, the Amount of the transaction and a way for chosing a cert for doing the digital signing & do the signing.

I concatenate the "Transfer To" Account no & the amount plus a nonce and this is the string which will be signed and sent to the backend.

I have searched a lot but haven't been able to figure out how to achieve - letting the user chose a cert - do the signing.

I know how the user can add certs to his personal truststore on Windows. But how would I ask the browser to show him certs to chose from?

How does the signing get done - I really don't want to write crypto code in Javascript!!! So is the alternative having an ActiveX or a Java Applet? Is there a better way? Is there a way to ask the browser to use the cert and do the signing?

I have not decided on a platform/framework/language for now - so this question is rather generic.

I have searched a lot for this kind of info without luck - all I get is tutorials on digital signing, tutorials on how to enable PKI in Apache etc.

If someone feels my whole approach is wrong & there is a better way to do digital signing in a web-app - feel free to suggest those alternatives also.

user93353
  • 441
  • 3
  • 7
  • 18
  • @dan1111 - My application is never going to be deployed at any bank - I am doing this just to learn - as I explained in my question. Let me edit the question and make it even clearer. – user93353 Jun 07 '13 at 11:58
  • My apologies for misreading the question. –  Jun 07 '13 at 12:00
  • Are you asking about signing a message or is your goal mutual authentication as defined by HTTPS? – Uwe Plonus Jun 07 '13 at 12:09
  • @UwePlonus No - I am not looking at authentication - I am looking a signing a message - in this case the message will be TransferToAcctNumber+TransferAmount – user93353 Jun 07 '13 at 12:12
  • @user93353 then please read this [question](http://programmers.stackexchange.com/questions/200790/how-easy-is-to-hack-javascript-in-a-browser). It should explain clearly enough why this will not work as intended. – Uwe Plonus Jun 07 '13 at 12:15
  • @UwePlonus - I understand javascript is not the right way to do it. As a matter of fact, I wanted to write in the question "I really don't want to write crypto code in Javascript!!! " - but ended up writing "I really write crypto code in Javascript!!!". Sorry about that. Corrected now. However, what's the alternative - how does one implement transaction signing in web based applications? – user93353 Jun 07 '13 at 12:19
  • In additiona to what others have said, I note that the payload you intend to sign is just `transfer-to-account|amount`. Note that this would be vulnerable to a replay attack: anyone who can observe a successful transaction can cause it to be repeated again and again even though they can't generate new, different, valid transactions. This will result in transfering a multiple of the intended amount! – Celada Jun 07 '13 at 14:31
  • @Celada - good point - maybe it should 'transfer-to|amount|datetime' and should be valid only for a +-delta of the datetime. – user93353 Jun 07 '13 at 15:13
  • @user93353 That helps, but for banking I would do more: I would favour a challenge-response type protocol: the server issues a one-time ticket (a random number), the ticket goes into the signed request payload, and the server cancels the ticket the first time it gets it back. – Celada Jun 07 '13 at 15:26
  • @Celada - Yes, a nonce. – user93353 Jun 07 '13 at 15:30
  • Just to make certain I am reading this correctly, your requirement is to do the signing on the client end in their browser before the initial post? or just that it is signed by the time it reaches the underlying accounting/transaction/batch system? – Bill Jun 10 '13 at 18:21
  • @Bill - signing has to be done on the client side - because it's the client who has the cert. I don't get how the signing can be done anywhere else - what would be the point? – user93353 Jun 10 '13 at 19:05
  • I missed your comment here until now. You answered my question, but to answer yours there are many cases where you might want a UI server to sign a message to a underlying system. I used to work on a fair bit of financial stuff that did things like this. The browser is the client to a webserver, but the webserver is a client so a service so there is a security concern at both tiers potentially unless you are running your production system in an isolated subnet. Did you ever come up with a solution you were happy with here? – Bill Jul 09 '13 at 14:30

1 Answers1

1

I could be wrong about this, but as far as I know without resorting to implementing crypto in JavaScript or using some manner of plugin you cannot do exactly what you are attempting.

There is something close that is unpopular, but fairly well supported: Client Side Certificates

The general idea is that the client has a certificate in their keychain and that certificate is examined when they request a secured resource as part of the authorization sequence. After that point the communication proceeds over normal everyday SSL.

In your case if you were to have a web service that was behind SSL and a form that posts the transfer, transferTo and nonce and the service was configured appropriately to request client certificates the service would respond to the initial request with a request for credentials and the distinguished names of issuers it will accept. If the browser has more than one client certificate from that list it should prompt the user to select.

The rest of the conversation is just handled like any other SSL as I understand it, but you should then have access to the client certificate as part of the request object from the server end of things.

This is not exactly what you were asking for, but to my knowledge this is the closest you can get without doing something non-standard. The communication is secure because of the SSL, the user has proven they have a copy of the certificate and on the server end you can use the certificate to check that the user matches who they claim to be as an additional authentication factor. The message is not literally signed with the key, but the SSL communication channel the message traveled over was verified with the client key.

A stack overflow that discusses this further (see first answer & links):

https://stackoverflow.com/questions/1193013/ssl-client-cert-verification-optimisation

Examples of how you might set it up if you are in Microsoft land:

http://woloski.com/2012/08/04/securing-aspnet-webapi-with-clientcerts/

http://support.microsoft.com/kb/315588 (older versions)

Bill
  • 8,330
  • 24
  • 52
  • The point is that I don't want to ask for a client cert at the beginning - i.e. at that time customer needs only userid password - so I cannot turn on 2 way ssl certs at the beginning. – user93353 Jun 11 '13 at 23:57
  • I have never done it that way, but if the service endpoint you were posting to was requiring a client certificate and the remainder of the site was not I think you would achieve the result you are looking for in that regard. That is why I specified the client cert part on the service endpoint only. – Bill Jun 12 '13 at 14:01