25

I have to transfer some sensitive information over a JavaScript AJAX Call, over an unencrypted channel (HTTP, not HTTPS).

I'd like to encrypt the data, but encryption on the JavaScript side means I expose the key, which makes symmetric encryption only an exercise in security by obscurity.

Is there any asymmetric encryption for JavaScript? That way, I can keep the Server decryption key secret. (I'm not worried about the security of Server > JavaScript messages, only about the security of a certain JavaScript > Server message)

Michael Stum
  • 177,530
  • 117
  • 400
  • 535

5 Answers5

16

The reason why you need encryption at all is probably to protect against a man-in-the-middle. There are scenarios where an attacker is able to sniff at the traffic without being able to change it. This solution would protect against that threat, but it would provide no protection at all against a man-in-the-middle that is able to modify the traffic.

If the attacker can change the traffic, then he will also be able to change the script that does the encryption. The easiest attack would be to just remove the encryption completely from the script. If you don't have https, and a man-in-the-middle is possible (which is the case in almost every scenario) then you don't have any control at all over the html or javascript that is presented to the end user. The attacker may rewrite your html code and javascript completely, disablign encryption, creating new form fields in your form etc. Https is a prerequisite for secure communication in the web-channel.

sstendal
  • 3,148
  • 17
  • 22
  • Agreed, encryption in JavaScript is a bad idea. Additionally, at the moment no JavaScript implementation in the browser has any secure random number generation. This means any cryptography implemented in JavaScript will be **broken**, regardless of other threats. – molf May 25 '11 at 09:37
  • Thanks. That makes sense - I was mainly considering sniffing, not manipulation. I'll think about this some more and see if HTTPS is an option somehow. – Michael Stum May 25 '11 at 15:42
  • Actually, unless implemented *really* carefully, just performing a normal asymmetric encryption does not protect against eavesdropping either. Normally you encrypt a symmetric key with the RSA key, then perform the encryption with the symmetric session key. That encryption is bound to use CBC with some kind of padding. Since the service handling the post is online, you've now created a scheme that is vulnerable against padding oracle attacks (isn't cryptography fun?). – Maarten Bodewes May 26 '11 at 11:30
  • 1
    @sstendal : What if the connection is https. Can I then use encryption in javascript, then? I need to do public key encryption. The user's form fields are signed by his private key on the client side(the client has to give location of the keystore containing the private key ). And are sent to to the server. The server there verifies that the right user has signed by verifying the signature using the corresponding public key. But I guess it is not possible. Because javascript is sandboxed. You cannot access localhost files, I guess. Please correct me IF I am worng. IS there any way aound this? – Ashwin May 03 '12 at 09:50
  • We now have Subresource Integrity https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity. This will protect the javascript being served to the browser. – user2677034 Sep 06 '19 at 15:04
  • While I agree with the general advice, I strongly oppose the claim that encryption in JavaScript is _generally_ a bad idea. There is no such thing as one hundred percent security in software. Relying on a single mechanism, such as https, to protect all of your data, is therefore bad advice. Https does not fully protect against man-in-the-middle attacks and sniffing. Using encryption in JavaScript - as an _additional_ countermeasure - can considerably increase the hurdle for overcoming an authentication scheme. – Andreas Vogl Apr 01 '21 at 15:06
13

I've done it. I use this JavaScript client-side asymetric RSA encryption to prevent the login credentials to be send in plain text over HTTP.

The goal is to prevent login request replay attacks based on network sniffing. Of course, this is not as secure as HTTPS since it would not resist to man-in-the-middle attacks, but it can be sufficient for local networks.

The client-side encryption uses Travis Tridwell's excellent work which is based on JSBN. Travis' web page can also generate the private and public RSA keys (if you are too lazy to use openssl). The keys are generated in PKCS#1 PEM format. I encrypt username+password+timeInMs+timezone so that the encrypted content changes at each login.

On the server-side, my Java code read read the PKCS#1 PEM file using Apache JMeter's org.apache.jmeter.protocol.oauth.sampler.PrivateKeyReader :

PrivateKey pk = (new PrivateKeyReader("myPrivateKeyFile.pem")).getPrivateKey();

Then I decrypt the encrypted content using

byte[] enc = DatatypeConverter.parseBase64Binary(clientData);
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE, pk);
byte[] dec = rsa.doFinal(enc);
String out = new String(dec, "UTF8");

Then I check if the client-side timestamp/timezone match the server-side timestamp/timezone. If the delay is less than a few seconds, the login process continues. Otherwise the request is considered a replay attack and the login fails.

Julien Kronegg
  • 4,968
  • 1
  • 47
  • 60
5

asymmetric public key/ private key is the only way to do this. To protect against MIM attacks the server can hash the public key with the users password, then the user (in the browser) re-computes the hash - if they match then the user can be confident that the public key sent from the server has not been tampered with - this relies on the fact that only the server and the user know the users password.

PS I wanted to write this as a comment as that would be more appropiate than an answer, but I don't have enough points :)

See:openpgp.js for examples

user2677034
  • 624
  • 10
  • 20
4

This question seems to have what you're after, Javascript cryptography library to sign form data in browser The PGP link: http://www.hanewin.net/encrypt/ has RSA

Community
  • 1
  • 1
dnolan
  • 2,349
  • 19
  • 21
4

Are the Server > JavaScript messages sent over HTTPS?

If not, nothing prevents a man in the middle from changing the scripts. Any encryption will be useless if the code that has access to the unencrypted data is compromised.

Baffe Boyois
  • 2,120
  • 15
  • 15
  • 1
    My question says that it's HTTP, not HTTPS. That's why I'm looking at asymmetric encryption, so that I can keep the decryption key on the server side. That's precisely what asymmetric encryption helps solving: A man in the middle can get the encrypted message, the keys used to encrypt it, but without the key to decrypt it it's not much good. – Michael Stum May 24 '11 at 22:19
  • 5
    A man in the middle attack can also change the pubic key. You need some form of authentication as well, which is kind of hard to do from the perspective of a script running in a browser window. – Maarten Bodewes May 24 '11 at 23:16
  • @owl *What* kind of key?!? Anyway, mitm can dispense with all the encryption entirely and just send the sensitive data collected by the browser anywhere he wants. – ErikE May 25 '11 at 08:17
  • 1
    @Erik: The asymmetric public key of course. And you are right, if the attacker can change the public key, he/she can also change the code on the page. So this scheme only protects against eavesdropping. Just as long as Michael is aware that this scheme does not protect against MITM. – Maarten Bodewes May 25 '11 at 20:47
  • 1
    @owl look carefully; you said pubic key. – ErikE May 25 '11 at 21:38
  • @Erik: Yes, that's what you do with encryption, you use the public key on the page and the private key on the server. The public key anyone can change if you don't authenticate, so that's the key that is vulnerable to man in the middle attacks. – Maarten Bodewes May 26 '11 at 11:26
  • 2
    @owl I fully understand public/private key cryptography. :) Please click this link and read the definition of **[pubic](http://dictionary.reference.com/browse/pubic).** – ErikE May 26 '11 at 16:08
  • To prevent the javascript being altered consider using Subresource Integrity:https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity – user2677034 May 18 '19 at 19:16