4
$\begingroup$

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.

$\endgroup$
11
  • 3
    $\begingroup$ Are you using HTTPS? Without HTTPS a webapplication has no hope of being secure. $\endgroup$ Sep 6, 2013 at 12:02
  • $\begingroup$ The data goes over Web Sockets. $\endgroup$
    – C1D
    Sep 6, 2013 at 12:02
  • 3
    $\begingroup$ It still matters if your website was loaded over SSL (i.e. uses HTTPS) and if the web sockets run over SSL. $\endgroup$ Sep 6, 2013 at 12:04
  • 3
    $\begingroup$ 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. $\endgroup$
    – hunter
    Sep 6, 2013 at 12:17
  • 1
    $\begingroup$ @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). $\endgroup$
    – dlongley
    Nov 1, 2013 at 17:43

3 Answers 3

5
$\begingroup$

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.

$\endgroup$
4
  • $\begingroup$ 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. $\endgroup$
    – Maarten Bodewes
    Sep 6, 2013 at 22:42
  • $\begingroup$ 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. $\endgroup$
    – Ninveh
    Sep 7, 2013 at 0:47
  • $\begingroup$ 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. $\endgroup$
    – C1D
    Sep 7, 2013 at 5:56
  • $\begingroup$ 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. $\endgroup$
    – Maarten Bodewes
    Sep 7, 2013 at 16:17
2
$\begingroup$

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

Like the accepted answer already stated: If you implemented it well and if there is no MITM (which can be handled by using HTTPS), then it is rather difficult to forge the RSA signatures.

Yet, at the time of writing this, I would be cautious when it comes to Javascript cryptography.

It’s around and about 3 years after the question was posted and Javascript still isn’t a language where you’ll want to base your security upon. That is, unless you would use the related functionalities WebCryptoAPI provides – which still isn’t a full standard. Simpler said: even when using 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.

Also, when thinking cryptographic security, you have to remind yourself that Javascript – as a scripting language – relies on a Javascript engine to be interpreted (provided by a web browsing client, or mutations like NODEjs). This means that you have to ensure you can trust the engines your users are going to be runing the Javascript signature script(s) on… which would mean you either have to trust the 3rd party (or parties) that compiled it, or you have to review the engine’s sourcecode yourself and then compile-your-own. The effort for the later will greatly depend on the individual scenario. (eg: Will all clients be using the same Javascript engine to run your script? Can it be assumed that users are going to run your scripts on secure systems? etc.)

All the above merely scratches the surface, showing a few of the many reasons why I‘ld personally tend to currently discourage relying on Javascript if you really expect to achieve strong cryptographic security”.

Now, don’t get me wrong: if you implement things correctly et al, you can somewhat limit risks to a minimum. Nevertheless, it’s still a bit like tap-dancing in a minefield because potential attack vectors are all around you when you use Javascript for cryptographic purposes… and Javascript itself simply doesn’t provide some of the low-level functionality (like – for example – C does) you’ld need to safeguard against some of those potential attack vectors. Lucky for the questioned scenario: (RSA) signature schemes are not as hard to push into a safer corner than some of the other cryptographic schemes out there… if you watch out for the pitfalls.

Last but not least: I’ll gladly agree that Javascript-based cryptography could become a very usable and valid option once WebCryptoAPI has been rendered into a feature-complete and well-vetted API. But until that day comes, I am a bit reluctant to generally call any Javascript crypto-implementation “safe” without pointing at potential risks – especially when you’re relying on 3rd party Javascript libraries instead of what WebCryptoAPI might already have to offer.


As (rather lengthly) aside, I’ld like to point to a few things that are worth considering:

  • 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.

TL;DR – The term “safe” is a bit relative in the questioned scenario.

$\endgroup$
1
  • $\begingroup$ Comments are not for extended discussion; this conversation has been moved to chat. $\endgroup$
    – e-sushi
    Apr 3, 2016 at 8:17
1
$\begingroup$

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.

$\endgroup$
1
  • 1
    $\begingroup$ 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. $\endgroup$
    – v6ak
    Jan 17, 2015 at 9:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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