Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm currently working on a secure open source messaging system (https://github.com/DSMNET/DSMNET). I'm currently using the cryptico.js (https://github.com/wwwtyro/cryptico) library to encrypt all the messages sent.

Now to authenticate users my server will send a random string and the client will encrypt the string and sign it. The server will check if the signature matches the public key stored for the user. Users will generate their public and private key with their password.

I would like to know if using Javascript RSA and using RSA signatures to authenticate is safe or can people forge RSA signatures.

Thanks

share|improve this question
3  
Are you using HTTPS? Without HTTPS a webapplication has no hope of being secure. – CodesInChaos Sep 6 '13 at 12:02
    
The data goes over Web Sockets. – C1D Sep 6 '13 at 12:02
3  
It still matters if your website was loaded over SSL (i.e. uses HTTPS) and if the web sockets run over SSL. – CodesInChaos Sep 6 '13 at 12:04
3  
The point that @CodesInChaos is making is that the javascript source code itself (and not just the user data) needs to be downloaded by the client over HTTPS, otherwise it can be modified in transit to behave in a malicious way. Read this before proceeding. – hunter Sep 6 '13 at 12:17
1  
@C1D, if the private key can be accessed via JS, then the server can access it (and could, for example, send it to the server). The user must trust that the server won't do so, but it is technically possible. Users should know this if it affects their privacy (they shouldn't export and use the private keys in other systems, for instance). – dlongley Nov 1 '13 at 17:43
up vote 3 down vote accepted

If you implemented it well, and there is no MITM (i.e. use authenticated comm channel), then it is difficult to forge the RSA signatures (meaning you can use them safely).

However, in your implementation there are 2 other major factors that you need to consider:

  1. One is the use of Javascript as a coding medium: there are many who consider Javascript to be a bad languange to use for writing security code due to some notable exposure to adversaries. I personally am not in that camp - if you take good care of securing your environment where you run the JS code you will be OK.

    Also, there are some advantages of letting the user's browser do the work (and Java has its own set of implementation / management problems), this may be a prudent choice.

  2. The second point is a major one: you selected “cryptico” engine, and we don't know how well the guy who wrote and modified the code behaved.

    Some critical security routines there were modified by him, and this should ring a big red alarm bell over its usage. If you plan to use it for anything important, you need to pass the published code through a critical security/cryptographic review before usage.

share|improve this answer
    
JavaScript usually does not have a trust store. You may not have a secure random generator either, generally a requirement to perform encryption. Downloading the application has security drawbacks even if SSL is deployed. There are few - if any - trustworthy crypto libraries for JavaScript. It runs slow and dynamic typing makes it very easy to make mistakes. – Maarten Bodewes Sep 6 '13 at 22:42
    
All those negatives may or may not be practically meaningful - depending upon the application and environment. The Stanford's SJCL is a reasonable implementation, including the Fortuna-based RNG (granted that, since JS can't access system params as native apps do, the available entropy pool is not as strong, but it is still reasonable for practical use). If you download the code not as embedded in HTML page but as a packaged file to run locally (with a hash fingerprint), then I would consider it trustworthy. To fend off mistakes, need to run some test vectors during code review. – Ninveh Sep 7 '13 at 0:47
    
Thanks for that. I will have a look at using Java for encryption. I will also see if there are any other RSA library's created by more trusted members in the community. – C1D Sep 7 '13 at 5:56
    
Later JavaScript engines may be able to access an entropy source, but I don't think the use is widespread just yet. Random numbers are required for almost any crypto. SJCL is the implementation that is maintained by a single person (who just quit, fortunately somebody else has taken over). The first time I used it I found out that it forgot to take any of the AAD into account when generating the authentication tag (using the convenience library). SJCL has come from a university paper that focuses on JavaScript performance. – Maarten Bodewes Sep 7 '13 at 16:17

RSA on itself is never safe! You must use proper functions to handle padding and probabilistic signing correctly. Otherwise your protocol is vulnerable to a bunch of attacks. PKCS #1 defines secure and well established algorithms like RSAES-OAEP and RSASSA-PSS. RSA without a padding or signature scheme is like using a block cipher in ECB mode.

JavaScript RSA implementations may be vulnerable to side channel attacks, too. Timing analysis attacks are a serious issue. Your code's run time must never depend on input from an untrustworthy source. However it's nearly impossible to know how a JavaScript engine is optimizing your code. There are just too many browsers with too many different versions and implementation of JS engines.

A very simple approach for constant run time uses sleep to archive constant time (pseudo code):

runtime = 2 seconds # twice as long as the slowest machine
start = time()
do_rsa()
end = time()
sleepduration = sleeptime + start - end
if sleeptime < 0:
    error()
sleep(sleepduration)

Please don't fall for the temptation to do sleep(random()). It's not safe.

share|improve this answer
1  
This hack however does not seem to mitigate some HyperThreading-related attacks. That is, another process running on the same physical core might see some variance in the performance depending on the plaintext or key used. – v6ak Jan 17 '15 at 9:33

Is javascript RSA signing safe?
…is safe or can people forge…

In contrast to the accepted answer, I would not call it “safe” from a cryptographic point of view and I would definitely not say that if you take good care of securing your environment where you run the JS code you will be OK. because the sad fact is: that’s not enough to ensure cryptographic “safety”.

About 3 years after the question was posted, javascript still isn’t a language where you’ll want to base your security on. That is, unless you would use the related functionalities WebCryptoAPI provides. But even if you use the WebCryptoAPI, you should remind yourself of the fact that that API is still in it’s infance (W3C Candidate Recommendation at the time of writing this) and definitely lacks some important corner stones which might or might not incubate yet-to-be-discovered attack vectors.

At the same time, attacks get better – if not scary. For example, you might want to check the paper “The Spy in the Sandbox -- Practical Cache Attacks in Javascript” (PDF), published 25 Feb 2015:

We present the first micro-architectural side-channel attack which runs entirely in the browser. In contrast to other works in this genre, this attack does not require the attacker to install any software on the victim's machine -- to facilitate the attack, the victim needs only to browse to an untrusted webpage with attacker-controlled content. This makes the attack model highly scalable and extremely relevant and practical to today's web, especially since most desktop browsers currently accessing the Internet are vulnerable to this attack.

Our attack, which is an extension of the last-level cache attacks of Yarom et al., allows a remote adversary recover information belonging to other processes, other users and even other virtual machines running on the same physical host as the victim web browser. We describe the fundamentals behind our attack, evaluate its performance using a high bandwidth covert channel and finally use it to construct a system-wide mouse/network activity logger. Defending against this attack is possible, but the required countermeasures can exact an impractical cost on other benign uses of the web browser and of the computer.

(emphasis mine)

Read that again: “recover information belonging to other processes, other users and even other virtual machines”. Now, guess how safe your signatures will be from that attack angle.

This is only one of the many reasons why I would recommend not to rely on javascript to provide strong cryptographic security when it comes to authenticating users or trying to secure RSA signature functionality.

I’ll gladly agree that javascript-based cryptography might become a valid option when WebCryptoAPI has been rendered into a feature-complete and well-vetted option. But until that day comes, I am reluctant to call any javascript crypto-attempt “safe” – especially when you’re relying plain javascript solutions/libraries instead of what WebCryptoAPI might already have to offer.

TL;DR

Plain javascript solutions can not be considered “safe” at the time of writing this. Even when using “WebCryptoAPI”, you should keep in mind that it’s far from being feature-complete and/or well-vetted. It might still be vunerable to attacks you most probably haven’t yet been thinking about up until today.


Besides that…

Besides the dangers mentioned in my answer, I‘ld like to point to a few things others already stated:

  • Comments (1, 2) by CodesInChaos:
    Are you using HTTPS? Without HTTPS a webapplication has no hope of being secure. … It still matters if your website was loaded over SSL (i.e. uses HTTPS) and if the web sockets run over SSL.
  • Comment (1) by Hunter:
    The point that @CodesInChaos is making is that the javascript source code itself (and not just the user data) needs to be downloaded by the client over HTTPS, otherwise it can be modified in transit to behave in a malicious way. Read http://www.matasano.com/articles/javascript-cryptography/ before proceeding.
  • Comments (1, 2) by dlongley:
    Keep in mind that server has complete access to the users' private keys in the system you describe (and they should know that if it may affect their privacy). … if the private key can be accessed via JS, then the server can access it (and could, for example, send it to the server). The user must trust that the server won't do so, but it is technically possible. Users should know this if it affects their privacy (they shouldn't export and use the private keys in other systems, for instance).
  • Answer (1) by Ninveh:
    … and we don't know how well the guy who wrote and modified the code behaved. Some critical security routines there were modified by him, and this should ring a big red alarm bell over its usage. If you plan to use it for anything important, you need to pass the published code through a critical security/cryptographic review before usage.
  • Comment (1) by C1D – the person that asked the question:
    The client stores the private key not the server. My protocol will provide an official open source client but theoretically if a user enters his password into a rouge client it could steal it.

That somewhat summarizes the most obvious safety issues related to the questioned scenario.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.