Are there any SHA-256 javascript implementations that are generally considered trustworthy?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







63















I am writing a login for a forum, and need to hash the password client side in javascript before sending it on to the server. I'm having trouble figuring out which SHA-256 implementation I can actually trust. I was expecting there to be some kind of authoritative script that everyone used, but I'm finding loads of different projects all with their own implementations.



I realize using other people's crypto is always a leap of faith unless you're qualified to review it yourself, and that there is no universal definition of "trustworthy", but this seems like something common and important enough that there ought to be some kind of consensus on what to use. Am I just naive?



Edit since it comes up a lot in the comments: Yes, we do a more stringent hash again on the server side. The client side hashing is not the final result that we save in the database. The client side hashing is because the human client requests it. They have not given a specific reason why, probably they just like overkill.










share|improve this question













migrated from security.stackexchange.com Aug 20 '13 at 15:20


This question came from our site for information security professionals.














  • 7





    Not to get off topic, but why are you hashing the password on the client side?

    – Steve
    Aug 19 '13 at 17:46






  • 4





    @ddyer Not even close. "Don't roll your own" applies to inventing your own algorithm, writing your own implementation of an algorithm, developing your own protocol on top of crypto algorithms, or pretty much anything above using as high-level an abstraction as is available. If you think you'll be safe sticking to a secure core, and only writing glue code, you're gonna have a bad time.

    – Stephen Touset
    Aug 19 '13 at 18:07






  • 22





    if you use a hashed password without a challenge/response protocol, then the hashed password IS the password and it's really the same as transmitting the password in clear text.

    – ddyer
    Aug 19 '13 at 18:29






  • 20





    @ddyer There is some value in protecting the user's plaintext password for all the other sites they might use it on, if not for our site in particular. It's an easy fix that maybe won't help us but can potentially help the user if we screw up somewhere. And like I said, client request, nothing I can do about it even if I wanted to.

    – jono
    Aug 19 '13 at 18:36






  • 3





    @Anorov I'm more than open to having my mind changed :) but in this case, I don't really understand how your point applies. We hash the password twice: once on the client side with a simple SHA-256, and once on the server side with something more demanding. The first to protect the plaintext in case of MITM or similar, and the second for brute protection. Even if you got a hold of the database and the admin hash you couldn't use that directly to validate the login.

    – jono
    Aug 19 '13 at 20:00


















63















I am writing a login for a forum, and need to hash the password client side in javascript before sending it on to the server. I'm having trouble figuring out which SHA-256 implementation I can actually trust. I was expecting there to be some kind of authoritative script that everyone used, but I'm finding loads of different projects all with their own implementations.



I realize using other people's crypto is always a leap of faith unless you're qualified to review it yourself, and that there is no universal definition of "trustworthy", but this seems like something common and important enough that there ought to be some kind of consensus on what to use. Am I just naive?



Edit since it comes up a lot in the comments: Yes, we do a more stringent hash again on the server side. The client side hashing is not the final result that we save in the database. The client side hashing is because the human client requests it. They have not given a specific reason why, probably they just like overkill.










share|improve this question













migrated from security.stackexchange.com Aug 20 '13 at 15:20


This question came from our site for information security professionals.














  • 7





    Not to get off topic, but why are you hashing the password on the client side?

    – Steve
    Aug 19 '13 at 17:46






  • 4





    @ddyer Not even close. "Don't roll your own" applies to inventing your own algorithm, writing your own implementation of an algorithm, developing your own protocol on top of crypto algorithms, or pretty much anything above using as high-level an abstraction as is available. If you think you'll be safe sticking to a secure core, and only writing glue code, you're gonna have a bad time.

    – Stephen Touset
    Aug 19 '13 at 18:07






  • 22





    if you use a hashed password without a challenge/response protocol, then the hashed password IS the password and it's really the same as transmitting the password in clear text.

    – ddyer
    Aug 19 '13 at 18:29






  • 20





    @ddyer There is some value in protecting the user's plaintext password for all the other sites they might use it on, if not for our site in particular. It's an easy fix that maybe won't help us but can potentially help the user if we screw up somewhere. And like I said, client request, nothing I can do about it even if I wanted to.

    – jono
    Aug 19 '13 at 18:36






  • 3





    @Anorov I'm more than open to having my mind changed :) but in this case, I don't really understand how your point applies. We hash the password twice: once on the client side with a simple SHA-256, and once on the server side with something more demanding. The first to protect the plaintext in case of MITM or similar, and the second for brute protection. Even if you got a hold of the database and the admin hash you couldn't use that directly to validate the login.

    – jono
    Aug 19 '13 at 20:00














63












63








63


20






I am writing a login for a forum, and need to hash the password client side in javascript before sending it on to the server. I'm having trouble figuring out which SHA-256 implementation I can actually trust. I was expecting there to be some kind of authoritative script that everyone used, but I'm finding loads of different projects all with their own implementations.



I realize using other people's crypto is always a leap of faith unless you're qualified to review it yourself, and that there is no universal definition of "trustworthy", but this seems like something common and important enough that there ought to be some kind of consensus on what to use. Am I just naive?



Edit since it comes up a lot in the comments: Yes, we do a more stringent hash again on the server side. The client side hashing is not the final result that we save in the database. The client side hashing is because the human client requests it. They have not given a specific reason why, probably they just like overkill.










share|improve this question














I am writing a login for a forum, and need to hash the password client side in javascript before sending it on to the server. I'm having trouble figuring out which SHA-256 implementation I can actually trust. I was expecting there to be some kind of authoritative script that everyone used, but I'm finding loads of different projects all with their own implementations.



I realize using other people's crypto is always a leap of faith unless you're qualified to review it yourself, and that there is no universal definition of "trustworthy", but this seems like something common and important enough that there ought to be some kind of consensus on what to use. Am I just naive?



Edit since it comes up a lot in the comments: Yes, we do a more stringent hash again on the server side. The client side hashing is not the final result that we save in the database. The client side hashing is because the human client requests it. They have not given a specific reason why, probably they just like overkill.







hash javascript sha256 sha2






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Aug 19 '13 at 17:15









jonojono

417176




417176




migrated from security.stackexchange.com Aug 20 '13 at 15:20


This question came from our site for information security professionals.









migrated from security.stackexchange.com Aug 20 '13 at 15:20


This question came from our site for information security professionals.










  • 7





    Not to get off topic, but why are you hashing the password on the client side?

    – Steve
    Aug 19 '13 at 17:46






  • 4





    @ddyer Not even close. "Don't roll your own" applies to inventing your own algorithm, writing your own implementation of an algorithm, developing your own protocol on top of crypto algorithms, or pretty much anything above using as high-level an abstraction as is available. If you think you'll be safe sticking to a secure core, and only writing glue code, you're gonna have a bad time.

    – Stephen Touset
    Aug 19 '13 at 18:07






  • 22





    if you use a hashed password without a challenge/response protocol, then the hashed password IS the password and it's really the same as transmitting the password in clear text.

    – ddyer
    Aug 19 '13 at 18:29






  • 20





    @ddyer There is some value in protecting the user's plaintext password for all the other sites they might use it on, if not for our site in particular. It's an easy fix that maybe won't help us but can potentially help the user if we screw up somewhere. And like I said, client request, nothing I can do about it even if I wanted to.

    – jono
    Aug 19 '13 at 18:36






  • 3





    @Anorov I'm more than open to having my mind changed :) but in this case, I don't really understand how your point applies. We hash the password twice: once on the client side with a simple SHA-256, and once on the server side with something more demanding. The first to protect the plaintext in case of MITM or similar, and the second for brute protection. Even if you got a hold of the database and the admin hash you couldn't use that directly to validate the login.

    – jono
    Aug 19 '13 at 20:00














  • 7





    Not to get off topic, but why are you hashing the password on the client side?

    – Steve
    Aug 19 '13 at 17:46






  • 4





    @ddyer Not even close. "Don't roll your own" applies to inventing your own algorithm, writing your own implementation of an algorithm, developing your own protocol on top of crypto algorithms, or pretty much anything above using as high-level an abstraction as is available. If you think you'll be safe sticking to a secure core, and only writing glue code, you're gonna have a bad time.

    – Stephen Touset
    Aug 19 '13 at 18:07






  • 22





    if you use a hashed password without a challenge/response protocol, then the hashed password IS the password and it's really the same as transmitting the password in clear text.

    – ddyer
    Aug 19 '13 at 18:29






  • 20





    @ddyer There is some value in protecting the user's plaintext password for all the other sites they might use it on, if not for our site in particular. It's an easy fix that maybe won't help us but can potentially help the user if we screw up somewhere. And like I said, client request, nothing I can do about it even if I wanted to.

    – jono
    Aug 19 '13 at 18:36






  • 3





    @Anorov I'm more than open to having my mind changed :) but in this case, I don't really understand how your point applies. We hash the password twice: once on the client side with a simple SHA-256, and once on the server side with something more demanding. The first to protect the plaintext in case of MITM or similar, and the second for brute protection. Even if you got a hold of the database and the admin hash you couldn't use that directly to validate the login.

    – jono
    Aug 19 '13 at 20:00








7




7





Not to get off topic, but why are you hashing the password on the client side?

– Steve
Aug 19 '13 at 17:46





Not to get off topic, but why are you hashing the password on the client side?

– Steve
Aug 19 '13 at 17:46




4




4





@ddyer Not even close. "Don't roll your own" applies to inventing your own algorithm, writing your own implementation of an algorithm, developing your own protocol on top of crypto algorithms, or pretty much anything above using as high-level an abstraction as is available. If you think you'll be safe sticking to a secure core, and only writing glue code, you're gonna have a bad time.

– Stephen Touset
Aug 19 '13 at 18:07





@ddyer Not even close. "Don't roll your own" applies to inventing your own algorithm, writing your own implementation of an algorithm, developing your own protocol on top of crypto algorithms, or pretty much anything above using as high-level an abstraction as is available. If you think you'll be safe sticking to a secure core, and only writing glue code, you're gonna have a bad time.

– Stephen Touset
Aug 19 '13 at 18:07




22




22





if you use a hashed password without a challenge/response protocol, then the hashed password IS the password and it's really the same as transmitting the password in clear text.

– ddyer
Aug 19 '13 at 18:29





if you use a hashed password without a challenge/response protocol, then the hashed password IS the password and it's really the same as transmitting the password in clear text.

– ddyer
Aug 19 '13 at 18:29




20




20





@ddyer There is some value in protecting the user's plaintext password for all the other sites they might use it on, if not for our site in particular. It's an easy fix that maybe won't help us but can potentially help the user if we screw up somewhere. And like I said, client request, nothing I can do about it even if I wanted to.

– jono
Aug 19 '13 at 18:36





@ddyer There is some value in protecting the user's plaintext password for all the other sites they might use it on, if not for our site in particular. It's an easy fix that maybe won't help us but can potentially help the user if we screw up somewhere. And like I said, client request, nothing I can do about it even if I wanted to.

– jono
Aug 19 '13 at 18:36




3




3





@Anorov I'm more than open to having my mind changed :) but in this case, I don't really understand how your point applies. We hash the password twice: once on the client side with a simple SHA-256, and once on the server side with something more demanding. The first to protect the plaintext in case of MITM or similar, and the second for brute protection. Even if you got a hold of the database and the admin hash you couldn't use that directly to validate the login.

– jono
Aug 19 '13 at 20:00





@Anorov I'm more than open to having my mind changed :) but in this case, I don't really understand how your point applies. We hash the password twice: once on the client side with a simple SHA-256, and once on the server side with something more demanding. The first to protect the plaintext in case of MITM or similar, and the second for brute protection. Even if you got a hold of the database and the admin hash you couldn't use that directly to validate the login.

– jono
Aug 19 '13 at 20:00












7 Answers
7






active

oldest

votes


















81














The Stanford JS Crypto Library contains an implementation of SHA-256. While crypto in JS isn't really as well-vetted an endeavor as other implementation platforms, this one is at least partially developed by, and to a certain extent sponsored by, Dan Boneh, who is a well-established and trusted name in cryptography, and means that the project has some oversight by someone who actually knows what he's doing. The project is also supported by the NSF.



It's worth pointing out, however...

... that if you hash the password client-side before submitting it, then the hash is the password, and the original password becomes irrelevant. An attacker needs only to intercept the hash in order to impersonate the user, and if that hash is stored unmodified on the server, then the server is storing the true password (the hash) in plain-text.



So your security is now worse because you decided add your own improvements to what was previously a trusted scheme.






share|improve this answer





















  • 19





    If you hash again on the server however, this practice is perfectly legitimate.

    – Nick Brunt
    Nov 3 '13 at 1:28






  • 9





    @NickBrunt if you hash on the server then you're not saving the transmitted password, but you haven't added any security beyond transmitting the original password as opposed to transmitting the password hash, since in either case what you're transmitting is the real password.

    – tylerl
    Nov 3 '13 at 1:34






  • 36





    True, but it's not worse than sending a password which is possibly used elsewhere on the Internet in plaintext.

    – Nick Brunt
    Nov 3 '13 at 1:43






  • 7





    I agree with @NickBrunt . It is better if the attacker reads a random hash string that may fit only with this particular app rather than the original password that may be used in several places.

    – Aebsubis
    May 28 '14 at 15:16








  • 6





    I need to use client-side hashing because i don't want the server to ever see the user's plaintext password. Not for added security to the service I'M providing, but towards the user. I'm not only saving the user's hash salted with a constant salt (constant per user, not globally) but also re-hashing it with a random session salt every login which DOES provide a little extra security over the network against sniffing. If the server gets compromised it's game over, but that's true for anything not truely p2p anyways.

    – Hatagashira
    Oct 11 '14 at 15:42





















16














On https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest I found this snippet that uses internal js module:



async function sha256(message) {
// encode as UTF-8
const msgBuffer = new TextEncoder('utf-8').encode(message);

// hash the message
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

// convert ArrayBuffer to Array
const hashArray = Array.from(new Uint8Array(hashBuffer));

// convert bytes to hex string
const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
return hashHex;
}


Note that crypto.subtle in only available on https or localhost - for example for your local development with python3 -m http.server you need to add this line to your /etc/hosts:
0.0.0.0 localhost



Reboot - and you can open localhost:8000 with working crypto.subtle.






share|improve this answer


























  • This is awesome. Thank you. Is a comparable API available in Node.js?

    – Con Antonakos
    Feb 2 '18 at 14:55











  • The builtin 'crypto' library should do just fine: nodejs.org/dist/latest-v11.x/docs/api/crypto.html

    – tytho
    Jan 6 at 19:42





















14














Forge's SHA-256 implementation is fast and reliable.



To run tests on several SHA-256 JavaScript implementations, go to http://brillout.github.io/test-javascript-hash-implementations/.



The results on my machine suggests forge to be the fastest implementation and also considerably faster than the Stanford Javascript Crypto Library (sjcl) mentioned in the accepted answer.



Forge is 256 KB big, but extracting the SHA-256 related code reduces the size to 4.5 KB, see https://github.com/brillout/forge-sha256






share|improve this answer

































    10














    No, there's no way to use browser JavaScript to improve password security. I highly recommend you read this article. In your case, the biggest problem is the chicken-egg problem:




    What's the "chicken-egg problem" with delivering Javascript cryptography?



    If you don't trust the network to deliver a password, or, worse, don't trust the server not to keep user secrets, you can't trust them to deliver security code. The same attacker who was sniffing passwords or reading diaries before you introduce crypto is simply hijacking crypto code after you do.




    [...]




    Why can't I use TLS/SSL to deliver the Javascript crypto code?



    You can. It's harder than it sounds, but you safely transmit Javascript crypto to a browser using SSL. The problem is, having established a secure channel with SSL, you no longer need Javascript cryptography; you have "real" cryptography.




    Which leads to this:




    The problem with running crypto code in Javascript is that practically any function that the crypto depends on could be overridden silently by any piece of content used to build the hosting page. Crypto security could be undone early in the process (by generating bogus random numbers, or by tampering with constants and parameters used by algorithms), or later (by spiriting key material back to an attacker), or --- in the most likely scenario --- by bypassing the crypto entirely.



    There is no reliable way for any piece of Javascript code to verify its execution environment. Javascript crypto code can't ask, "am I really dealing with a random number generator, or with some facsimile of one provided by an attacker?" And it certainly can't assert "nobody is allowed to do anything with this crypto secret except in ways that I, the author, approve of". These are two properties that often are provided in other environments that use crypto, and they're impossible in Javascript.




    Basically the problem is this:




    • Your clients don't trust your servers, so they want to add extra security code.

    • That security code is delivered by your servers (the ones they don't trust).


    Or alternatively,




    • Your clients don't trust SSL, so they want you use extra security code.

    • That security code is delivered via SSL.


    Note: Also, SHA-256 isn't suitable for this, since it's so easy to brute force unsalted non-iterated passwords. If you decide to do this anyway, look for an implementation of bcrypt, scrypt or PBKDF2.






    share|improve this answer





















    • 1





      This is not correct. The password security can be improved by hashing on the client side. It is also wrong that SHA-256 is unsuited as long as something like PBKDF2 is used on the server side. Thirdly, while the matasano article contains useful insight, the punch line is wrong since we now have browser apps that fundamentally change the chicken-and-egg issue.

      – user239558
      Oct 3 '13 at 23:14






    • 2





      You're right that PBKDF2 should be used on the client. The rage against client side javascript crypto assumes that the initial page and subsequent requests have the same security properties. That is obviously not true for browser apps where the initial page is installed separately and is static. It is also not true for any page with cache-forever semantics. In these cases, it is TOFU which is exactly the same as when installing a client side program. This can also be true in more complex setups where serving of static and dynamic pages are separated on the server.

      – user239558
      Oct 3 '13 at 23:31








    • 3





      It is legitimate to avoid system administrators to have access to user passwords, so hashing in the client side prevent DBAs or other IT professionals to see users passwords and try to reuse it to access other services/systems, since a lot of users repeat their passwords.

      – Yamada
      Apr 20 '16 at 12:27






    • 1





      @Xenland All you're doing is creating a new password which is "token + password". All of the original problems still apply. For example, an attacker can replace the JavaScript with code to send them the token + password.

      – Brendan Long
      Nov 16 '16 at 23:40






    • 1





      @Xenland The chicken and egg problem doesn't have anything to do with the requests you send. The problem is that your client is using JavaScript code that it downloaded over an insecure connection to do security work. The only way to safely send JavaScript to a web browser is to serve it over TLS, and once you do that, you don't need to do anything else because your connection is already secure. It doesn't matter what your protocol is if you're using JavaScript code that an attacker can just replace.

      – Brendan Long
      Nov 22 '16 at 14:13



















    6














    I found this implementation very easy to use. Also has a generous BSD-style license:



    jsSHA: https://github.com/Caligatio/jsSHA



    I needed a quick way to get the hex-string representation of a SHA-256 hash. It only took 3 lines:



    var sha256 = new jsSHA('SHA-256', 'TEXT');
    sha256.update(some_string_variable_to_hash);
    var hash = sha256.getHash("HEX");





    share|improve this answer































      5














      For those interested, this is code for creating SHA-256 hash using sjcl:



      import sjcl from 'sjcl'

      const myString = 'Hello'
      const myBitArray = sjcl.hash.sha256.hash(myString)
      const myHash = sjcl.codec.hex.fromBits(myBitArray)





      share|improve this answer



















      • 1





        This should be incorporated in the accepted answer for those who want to use the solution there. (Heck, even their own docs don't have a snippet like this)

        – MagicLegend
        Oct 5 '18 at 16:05



















      0














      Besides the Stanford lib that tylerl mentioned. I found jsrsasign very useful (Github repo here:https://github.com/kjur/jsrsasign). I don't know how exactly trustworthy it is, but i've used its API of SHA256, Base64, RSA, x509 etc. and it works pretty well. In fact, it includes the Stanford lib as well.



      If all you want to do is SHA256, jsrsasign might be a overkill. But if you have other needs in the related area, I feel it's a good fit.






      share|improve this answer



















      • 1





        It is safer and faster to use developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

        – Vitaly Zdanevich
        Jan 30 at 8:29











      • Agree, but to be fair,I answered this question in 2015 while mozilla's web crypto API specification was published Jan 2017

        – Faraway
        Feb 12 at 7:52












      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f18338890%2fare-there-any-sha-256-javascript-implementations-that-are-generally-considered-t%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      7 Answers
      7






      active

      oldest

      votes








      7 Answers
      7






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      81














      The Stanford JS Crypto Library contains an implementation of SHA-256. While crypto in JS isn't really as well-vetted an endeavor as other implementation platforms, this one is at least partially developed by, and to a certain extent sponsored by, Dan Boneh, who is a well-established and trusted name in cryptography, and means that the project has some oversight by someone who actually knows what he's doing. The project is also supported by the NSF.



      It's worth pointing out, however...

      ... that if you hash the password client-side before submitting it, then the hash is the password, and the original password becomes irrelevant. An attacker needs only to intercept the hash in order to impersonate the user, and if that hash is stored unmodified on the server, then the server is storing the true password (the hash) in plain-text.



      So your security is now worse because you decided add your own improvements to what was previously a trusted scheme.






      share|improve this answer





















      • 19





        If you hash again on the server however, this practice is perfectly legitimate.

        – Nick Brunt
        Nov 3 '13 at 1:28






      • 9





        @NickBrunt if you hash on the server then you're not saving the transmitted password, but you haven't added any security beyond transmitting the original password as opposed to transmitting the password hash, since in either case what you're transmitting is the real password.

        – tylerl
        Nov 3 '13 at 1:34






      • 36





        True, but it's not worse than sending a password which is possibly used elsewhere on the Internet in plaintext.

        – Nick Brunt
        Nov 3 '13 at 1:43






      • 7





        I agree with @NickBrunt . It is better if the attacker reads a random hash string that may fit only with this particular app rather than the original password that may be used in several places.

        – Aebsubis
        May 28 '14 at 15:16








      • 6





        I need to use client-side hashing because i don't want the server to ever see the user's plaintext password. Not for added security to the service I'M providing, but towards the user. I'm not only saving the user's hash salted with a constant salt (constant per user, not globally) but also re-hashing it with a random session salt every login which DOES provide a little extra security over the network against sniffing. If the server gets compromised it's game over, but that's true for anything not truely p2p anyways.

        – Hatagashira
        Oct 11 '14 at 15:42


















      81














      The Stanford JS Crypto Library contains an implementation of SHA-256. While crypto in JS isn't really as well-vetted an endeavor as other implementation platforms, this one is at least partially developed by, and to a certain extent sponsored by, Dan Boneh, who is a well-established and trusted name in cryptography, and means that the project has some oversight by someone who actually knows what he's doing. The project is also supported by the NSF.



      It's worth pointing out, however...

      ... that if you hash the password client-side before submitting it, then the hash is the password, and the original password becomes irrelevant. An attacker needs only to intercept the hash in order to impersonate the user, and if that hash is stored unmodified on the server, then the server is storing the true password (the hash) in plain-text.



      So your security is now worse because you decided add your own improvements to what was previously a trusted scheme.






      share|improve this answer





















      • 19





        If you hash again on the server however, this practice is perfectly legitimate.

        – Nick Brunt
        Nov 3 '13 at 1:28






      • 9





        @NickBrunt if you hash on the server then you're not saving the transmitted password, but you haven't added any security beyond transmitting the original password as opposed to transmitting the password hash, since in either case what you're transmitting is the real password.

        – tylerl
        Nov 3 '13 at 1:34






      • 36





        True, but it's not worse than sending a password which is possibly used elsewhere on the Internet in plaintext.

        – Nick Brunt
        Nov 3 '13 at 1:43






      • 7





        I agree with @NickBrunt . It is better if the attacker reads a random hash string that may fit only with this particular app rather than the original password that may be used in several places.

        – Aebsubis
        May 28 '14 at 15:16








      • 6





        I need to use client-side hashing because i don't want the server to ever see the user's plaintext password. Not for added security to the service I'M providing, but towards the user. I'm not only saving the user's hash salted with a constant salt (constant per user, not globally) but also re-hashing it with a random session salt every login which DOES provide a little extra security over the network against sniffing. If the server gets compromised it's game over, but that's true for anything not truely p2p anyways.

        – Hatagashira
        Oct 11 '14 at 15:42
















      81












      81








      81







      The Stanford JS Crypto Library contains an implementation of SHA-256. While crypto in JS isn't really as well-vetted an endeavor as other implementation platforms, this one is at least partially developed by, and to a certain extent sponsored by, Dan Boneh, who is a well-established and trusted name in cryptography, and means that the project has some oversight by someone who actually knows what he's doing. The project is also supported by the NSF.



      It's worth pointing out, however...

      ... that if you hash the password client-side before submitting it, then the hash is the password, and the original password becomes irrelevant. An attacker needs only to intercept the hash in order to impersonate the user, and if that hash is stored unmodified on the server, then the server is storing the true password (the hash) in plain-text.



      So your security is now worse because you decided add your own improvements to what was previously a trusted scheme.






      share|improve this answer















      The Stanford JS Crypto Library contains an implementation of SHA-256. While crypto in JS isn't really as well-vetted an endeavor as other implementation platforms, this one is at least partially developed by, and to a certain extent sponsored by, Dan Boneh, who is a well-established and trusted name in cryptography, and means that the project has some oversight by someone who actually knows what he's doing. The project is also supported by the NSF.



      It's worth pointing out, however...

      ... that if you hash the password client-side before submitting it, then the hash is the password, and the original password becomes irrelevant. An attacker needs only to intercept the hash in order to impersonate the user, and if that hash is stored unmodified on the server, then the server is storing the true password (the hash) in plain-text.



      So your security is now worse because you decided add your own improvements to what was previously a trusted scheme.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Mar 17 '17 at 13:14









      Community

      11




      11










      answered Aug 19 '13 at 22:44









      tylerltylerl

      23.6k1072101




      23.6k1072101








      • 19





        If you hash again on the server however, this practice is perfectly legitimate.

        – Nick Brunt
        Nov 3 '13 at 1:28






      • 9





        @NickBrunt if you hash on the server then you're not saving the transmitted password, but you haven't added any security beyond transmitting the original password as opposed to transmitting the password hash, since in either case what you're transmitting is the real password.

        – tylerl
        Nov 3 '13 at 1:34






      • 36





        True, but it's not worse than sending a password which is possibly used elsewhere on the Internet in plaintext.

        – Nick Brunt
        Nov 3 '13 at 1:43






      • 7





        I agree with @NickBrunt . It is better if the attacker reads a random hash string that may fit only with this particular app rather than the original password that may be used in several places.

        – Aebsubis
        May 28 '14 at 15:16








      • 6





        I need to use client-side hashing because i don't want the server to ever see the user's plaintext password. Not for added security to the service I'M providing, but towards the user. I'm not only saving the user's hash salted with a constant salt (constant per user, not globally) but also re-hashing it with a random session salt every login which DOES provide a little extra security over the network against sniffing. If the server gets compromised it's game over, but that's true for anything not truely p2p anyways.

        – Hatagashira
        Oct 11 '14 at 15:42
















      • 19





        If you hash again on the server however, this practice is perfectly legitimate.

        – Nick Brunt
        Nov 3 '13 at 1:28






      • 9





        @NickBrunt if you hash on the server then you're not saving the transmitted password, but you haven't added any security beyond transmitting the original password as opposed to transmitting the password hash, since in either case what you're transmitting is the real password.

        – tylerl
        Nov 3 '13 at 1:34






      • 36





        True, but it's not worse than sending a password which is possibly used elsewhere on the Internet in plaintext.

        – Nick Brunt
        Nov 3 '13 at 1:43






      • 7





        I agree with @NickBrunt . It is better if the attacker reads a random hash string that may fit only with this particular app rather than the original password that may be used in several places.

        – Aebsubis
        May 28 '14 at 15:16








      • 6





        I need to use client-side hashing because i don't want the server to ever see the user's plaintext password. Not for added security to the service I'M providing, but towards the user. I'm not only saving the user's hash salted with a constant salt (constant per user, not globally) but also re-hashing it with a random session salt every login which DOES provide a little extra security over the network against sniffing. If the server gets compromised it's game over, but that's true for anything not truely p2p anyways.

        – Hatagashira
        Oct 11 '14 at 15:42










      19




      19





      If you hash again on the server however, this practice is perfectly legitimate.

      – Nick Brunt
      Nov 3 '13 at 1:28





      If you hash again on the server however, this practice is perfectly legitimate.

      – Nick Brunt
      Nov 3 '13 at 1:28




      9




      9





      @NickBrunt if you hash on the server then you're not saving the transmitted password, but you haven't added any security beyond transmitting the original password as opposed to transmitting the password hash, since in either case what you're transmitting is the real password.

      – tylerl
      Nov 3 '13 at 1:34





      @NickBrunt if you hash on the server then you're not saving the transmitted password, but you haven't added any security beyond transmitting the original password as opposed to transmitting the password hash, since in either case what you're transmitting is the real password.

      – tylerl
      Nov 3 '13 at 1:34




      36




      36





      True, but it's not worse than sending a password which is possibly used elsewhere on the Internet in plaintext.

      – Nick Brunt
      Nov 3 '13 at 1:43





      True, but it's not worse than sending a password which is possibly used elsewhere on the Internet in plaintext.

      – Nick Brunt
      Nov 3 '13 at 1:43




      7




      7





      I agree with @NickBrunt . It is better if the attacker reads a random hash string that may fit only with this particular app rather than the original password that may be used in several places.

      – Aebsubis
      May 28 '14 at 15:16







      I agree with @NickBrunt . It is better if the attacker reads a random hash string that may fit only with this particular app rather than the original password that may be used in several places.

      – Aebsubis
      May 28 '14 at 15:16






      6




      6





      I need to use client-side hashing because i don't want the server to ever see the user's plaintext password. Not for added security to the service I'M providing, but towards the user. I'm not only saving the user's hash salted with a constant salt (constant per user, not globally) but also re-hashing it with a random session salt every login which DOES provide a little extra security over the network against sniffing. If the server gets compromised it's game over, but that's true for anything not truely p2p anyways.

      – Hatagashira
      Oct 11 '14 at 15:42







      I need to use client-side hashing because i don't want the server to ever see the user's plaintext password. Not for added security to the service I'M providing, but towards the user. I'm not only saving the user's hash salted with a constant salt (constant per user, not globally) but also re-hashing it with a random session salt every login which DOES provide a little extra security over the network against sniffing. If the server gets compromised it's game over, but that's true for anything not truely p2p anyways.

      – Hatagashira
      Oct 11 '14 at 15:42















      16














      On https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest I found this snippet that uses internal js module:



      async function sha256(message) {
      // encode as UTF-8
      const msgBuffer = new TextEncoder('utf-8').encode(message);

      // hash the message
      const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

      // convert ArrayBuffer to Array
      const hashArray = Array.from(new Uint8Array(hashBuffer));

      // convert bytes to hex string
      const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
      return hashHex;
      }


      Note that crypto.subtle in only available on https or localhost - for example for your local development with python3 -m http.server you need to add this line to your /etc/hosts:
      0.0.0.0 localhost



      Reboot - and you can open localhost:8000 with working crypto.subtle.






      share|improve this answer


























      • This is awesome. Thank you. Is a comparable API available in Node.js?

        – Con Antonakos
        Feb 2 '18 at 14:55











      • The builtin 'crypto' library should do just fine: nodejs.org/dist/latest-v11.x/docs/api/crypto.html

        – tytho
        Jan 6 at 19:42


















      16














      On https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest I found this snippet that uses internal js module:



      async function sha256(message) {
      // encode as UTF-8
      const msgBuffer = new TextEncoder('utf-8').encode(message);

      // hash the message
      const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

      // convert ArrayBuffer to Array
      const hashArray = Array.from(new Uint8Array(hashBuffer));

      // convert bytes to hex string
      const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
      return hashHex;
      }


      Note that crypto.subtle in only available on https or localhost - for example for your local development with python3 -m http.server you need to add this line to your /etc/hosts:
      0.0.0.0 localhost



      Reboot - and you can open localhost:8000 with working crypto.subtle.






      share|improve this answer


























      • This is awesome. Thank you. Is a comparable API available in Node.js?

        – Con Antonakos
        Feb 2 '18 at 14:55











      • The builtin 'crypto' library should do just fine: nodejs.org/dist/latest-v11.x/docs/api/crypto.html

        – tytho
        Jan 6 at 19:42
















      16












      16








      16







      On https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest I found this snippet that uses internal js module:



      async function sha256(message) {
      // encode as UTF-8
      const msgBuffer = new TextEncoder('utf-8').encode(message);

      // hash the message
      const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

      // convert ArrayBuffer to Array
      const hashArray = Array.from(new Uint8Array(hashBuffer));

      // convert bytes to hex string
      const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
      return hashHex;
      }


      Note that crypto.subtle in only available on https or localhost - for example for your local development with python3 -m http.server you need to add this line to your /etc/hosts:
      0.0.0.0 localhost



      Reboot - and you can open localhost:8000 with working crypto.subtle.






      share|improve this answer















      On https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest I found this snippet that uses internal js module:



      async function sha256(message) {
      // encode as UTF-8
      const msgBuffer = new TextEncoder('utf-8').encode(message);

      // hash the message
      const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

      // convert ArrayBuffer to Array
      const hashArray = Array.from(new Uint8Array(hashBuffer));

      // convert bytes to hex string
      const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
      return hashHex;
      }


      Note that crypto.subtle in only available on https or localhost - for example for your local development with python3 -m http.server you need to add this line to your /etc/hosts:
      0.0.0.0 localhost



      Reboot - and you can open localhost:8000 with working crypto.subtle.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 30 at 8:26

























      answered Jan 9 '18 at 5:05









      Vitaly ZdanevichVitaly Zdanevich

      2,65032143




      2,65032143













      • This is awesome. Thank you. Is a comparable API available in Node.js?

        – Con Antonakos
        Feb 2 '18 at 14:55











      • The builtin 'crypto' library should do just fine: nodejs.org/dist/latest-v11.x/docs/api/crypto.html

        – tytho
        Jan 6 at 19:42





















      • This is awesome. Thank you. Is a comparable API available in Node.js?

        – Con Antonakos
        Feb 2 '18 at 14:55











      • The builtin 'crypto' library should do just fine: nodejs.org/dist/latest-v11.x/docs/api/crypto.html

        – tytho
        Jan 6 at 19:42



















      This is awesome. Thank you. Is a comparable API available in Node.js?

      – Con Antonakos
      Feb 2 '18 at 14:55





      This is awesome. Thank you. Is a comparable API available in Node.js?

      – Con Antonakos
      Feb 2 '18 at 14:55













      The builtin 'crypto' library should do just fine: nodejs.org/dist/latest-v11.x/docs/api/crypto.html

      – tytho
      Jan 6 at 19:42







      The builtin 'crypto' library should do just fine: nodejs.org/dist/latest-v11.x/docs/api/crypto.html

      – tytho
      Jan 6 at 19:42













      14














      Forge's SHA-256 implementation is fast and reliable.



      To run tests on several SHA-256 JavaScript implementations, go to http://brillout.github.io/test-javascript-hash-implementations/.



      The results on my machine suggests forge to be the fastest implementation and also considerably faster than the Stanford Javascript Crypto Library (sjcl) mentioned in the accepted answer.



      Forge is 256 KB big, but extracting the SHA-256 related code reduces the size to 4.5 KB, see https://github.com/brillout/forge-sha256






      share|improve this answer






























        14














        Forge's SHA-256 implementation is fast and reliable.



        To run tests on several SHA-256 JavaScript implementations, go to http://brillout.github.io/test-javascript-hash-implementations/.



        The results on my machine suggests forge to be the fastest implementation and also considerably faster than the Stanford Javascript Crypto Library (sjcl) mentioned in the accepted answer.



        Forge is 256 KB big, but extracting the SHA-256 related code reduces the size to 4.5 KB, see https://github.com/brillout/forge-sha256






        share|improve this answer




























          14












          14








          14







          Forge's SHA-256 implementation is fast and reliable.



          To run tests on several SHA-256 JavaScript implementations, go to http://brillout.github.io/test-javascript-hash-implementations/.



          The results on my machine suggests forge to be the fastest implementation and also considerably faster than the Stanford Javascript Crypto Library (sjcl) mentioned in the accepted answer.



          Forge is 256 KB big, but extracting the SHA-256 related code reduces the size to 4.5 KB, see https://github.com/brillout/forge-sha256






          share|improve this answer















          Forge's SHA-256 implementation is fast and reliable.



          To run tests on several SHA-256 JavaScript implementations, go to http://brillout.github.io/test-javascript-hash-implementations/.



          The results on my machine suggests forge to be the fastest implementation and also considerably faster than the Stanford Javascript Crypto Library (sjcl) mentioned in the accepted answer.



          Forge is 256 KB big, but extracting the SHA-256 related code reduces the size to 4.5 KB, see https://github.com/brillout/forge-sha256







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jul 22 '15 at 19:13

























          answered Jul 22 '15 at 11:39









          brilloutbrillout

          6,33194965




          6,33194965























              10














              No, there's no way to use browser JavaScript to improve password security. I highly recommend you read this article. In your case, the biggest problem is the chicken-egg problem:




              What's the "chicken-egg problem" with delivering Javascript cryptography?



              If you don't trust the network to deliver a password, or, worse, don't trust the server not to keep user secrets, you can't trust them to deliver security code. The same attacker who was sniffing passwords or reading diaries before you introduce crypto is simply hijacking crypto code after you do.




              [...]




              Why can't I use TLS/SSL to deliver the Javascript crypto code?



              You can. It's harder than it sounds, but you safely transmit Javascript crypto to a browser using SSL. The problem is, having established a secure channel with SSL, you no longer need Javascript cryptography; you have "real" cryptography.




              Which leads to this:




              The problem with running crypto code in Javascript is that practically any function that the crypto depends on could be overridden silently by any piece of content used to build the hosting page. Crypto security could be undone early in the process (by generating bogus random numbers, or by tampering with constants and parameters used by algorithms), or later (by spiriting key material back to an attacker), or --- in the most likely scenario --- by bypassing the crypto entirely.



              There is no reliable way for any piece of Javascript code to verify its execution environment. Javascript crypto code can't ask, "am I really dealing with a random number generator, or with some facsimile of one provided by an attacker?" And it certainly can't assert "nobody is allowed to do anything with this crypto secret except in ways that I, the author, approve of". These are two properties that often are provided in other environments that use crypto, and they're impossible in Javascript.




              Basically the problem is this:




              • Your clients don't trust your servers, so they want to add extra security code.

              • That security code is delivered by your servers (the ones they don't trust).


              Or alternatively,




              • Your clients don't trust SSL, so they want you use extra security code.

              • That security code is delivered via SSL.


              Note: Also, SHA-256 isn't suitable for this, since it's so easy to brute force unsalted non-iterated passwords. If you decide to do this anyway, look for an implementation of bcrypt, scrypt or PBKDF2.






              share|improve this answer





















              • 1





                This is not correct. The password security can be improved by hashing on the client side. It is also wrong that SHA-256 is unsuited as long as something like PBKDF2 is used on the server side. Thirdly, while the matasano article contains useful insight, the punch line is wrong since we now have browser apps that fundamentally change the chicken-and-egg issue.

                – user239558
                Oct 3 '13 at 23:14






              • 2





                You're right that PBKDF2 should be used on the client. The rage against client side javascript crypto assumes that the initial page and subsequent requests have the same security properties. That is obviously not true for browser apps where the initial page is installed separately and is static. It is also not true for any page with cache-forever semantics. In these cases, it is TOFU which is exactly the same as when installing a client side program. This can also be true in more complex setups where serving of static and dynamic pages are separated on the server.

                – user239558
                Oct 3 '13 at 23:31








              • 3





                It is legitimate to avoid system administrators to have access to user passwords, so hashing in the client side prevent DBAs or other IT professionals to see users passwords and try to reuse it to access other services/systems, since a lot of users repeat their passwords.

                – Yamada
                Apr 20 '16 at 12:27






              • 1





                @Xenland All you're doing is creating a new password which is "token + password". All of the original problems still apply. For example, an attacker can replace the JavaScript with code to send them the token + password.

                – Brendan Long
                Nov 16 '16 at 23:40






              • 1





                @Xenland The chicken and egg problem doesn't have anything to do with the requests you send. The problem is that your client is using JavaScript code that it downloaded over an insecure connection to do security work. The only way to safely send JavaScript to a web browser is to serve it over TLS, and once you do that, you don't need to do anything else because your connection is already secure. It doesn't matter what your protocol is if you're using JavaScript code that an attacker can just replace.

                – Brendan Long
                Nov 22 '16 at 14:13
















              10














              No, there's no way to use browser JavaScript to improve password security. I highly recommend you read this article. In your case, the biggest problem is the chicken-egg problem:




              What's the "chicken-egg problem" with delivering Javascript cryptography?



              If you don't trust the network to deliver a password, or, worse, don't trust the server not to keep user secrets, you can't trust them to deliver security code. The same attacker who was sniffing passwords or reading diaries before you introduce crypto is simply hijacking crypto code after you do.




              [...]




              Why can't I use TLS/SSL to deliver the Javascript crypto code?



              You can. It's harder than it sounds, but you safely transmit Javascript crypto to a browser using SSL. The problem is, having established a secure channel with SSL, you no longer need Javascript cryptography; you have "real" cryptography.




              Which leads to this:




              The problem with running crypto code in Javascript is that practically any function that the crypto depends on could be overridden silently by any piece of content used to build the hosting page. Crypto security could be undone early in the process (by generating bogus random numbers, or by tampering with constants and parameters used by algorithms), or later (by spiriting key material back to an attacker), or --- in the most likely scenario --- by bypassing the crypto entirely.



              There is no reliable way for any piece of Javascript code to verify its execution environment. Javascript crypto code can't ask, "am I really dealing with a random number generator, or with some facsimile of one provided by an attacker?" And it certainly can't assert "nobody is allowed to do anything with this crypto secret except in ways that I, the author, approve of". These are two properties that often are provided in other environments that use crypto, and they're impossible in Javascript.




              Basically the problem is this:




              • Your clients don't trust your servers, so they want to add extra security code.

              • That security code is delivered by your servers (the ones they don't trust).


              Or alternatively,




              • Your clients don't trust SSL, so they want you use extra security code.

              • That security code is delivered via SSL.


              Note: Also, SHA-256 isn't suitable for this, since it's so easy to brute force unsalted non-iterated passwords. If you decide to do this anyway, look for an implementation of bcrypt, scrypt or PBKDF2.






              share|improve this answer





















              • 1





                This is not correct. The password security can be improved by hashing on the client side. It is also wrong that SHA-256 is unsuited as long as something like PBKDF2 is used on the server side. Thirdly, while the matasano article contains useful insight, the punch line is wrong since we now have browser apps that fundamentally change the chicken-and-egg issue.

                – user239558
                Oct 3 '13 at 23:14






              • 2





                You're right that PBKDF2 should be used on the client. The rage against client side javascript crypto assumes that the initial page and subsequent requests have the same security properties. That is obviously not true for browser apps where the initial page is installed separately and is static. It is also not true for any page with cache-forever semantics. In these cases, it is TOFU which is exactly the same as when installing a client side program. This can also be true in more complex setups where serving of static and dynamic pages are separated on the server.

                – user239558
                Oct 3 '13 at 23:31








              • 3





                It is legitimate to avoid system administrators to have access to user passwords, so hashing in the client side prevent DBAs or other IT professionals to see users passwords and try to reuse it to access other services/systems, since a lot of users repeat their passwords.

                – Yamada
                Apr 20 '16 at 12:27






              • 1





                @Xenland All you're doing is creating a new password which is "token + password". All of the original problems still apply. For example, an attacker can replace the JavaScript with code to send them the token + password.

                – Brendan Long
                Nov 16 '16 at 23:40






              • 1





                @Xenland The chicken and egg problem doesn't have anything to do with the requests you send. The problem is that your client is using JavaScript code that it downloaded over an insecure connection to do security work. The only way to safely send JavaScript to a web browser is to serve it over TLS, and once you do that, you don't need to do anything else because your connection is already secure. It doesn't matter what your protocol is if you're using JavaScript code that an attacker can just replace.

                – Brendan Long
                Nov 22 '16 at 14:13














              10












              10








              10







              No, there's no way to use browser JavaScript to improve password security. I highly recommend you read this article. In your case, the biggest problem is the chicken-egg problem:




              What's the "chicken-egg problem" with delivering Javascript cryptography?



              If you don't trust the network to deliver a password, or, worse, don't trust the server not to keep user secrets, you can't trust them to deliver security code. The same attacker who was sniffing passwords or reading diaries before you introduce crypto is simply hijacking crypto code after you do.




              [...]




              Why can't I use TLS/SSL to deliver the Javascript crypto code?



              You can. It's harder than it sounds, but you safely transmit Javascript crypto to a browser using SSL. The problem is, having established a secure channel with SSL, you no longer need Javascript cryptography; you have "real" cryptography.




              Which leads to this:




              The problem with running crypto code in Javascript is that practically any function that the crypto depends on could be overridden silently by any piece of content used to build the hosting page. Crypto security could be undone early in the process (by generating bogus random numbers, or by tampering with constants and parameters used by algorithms), or later (by spiriting key material back to an attacker), or --- in the most likely scenario --- by bypassing the crypto entirely.



              There is no reliable way for any piece of Javascript code to verify its execution environment. Javascript crypto code can't ask, "am I really dealing with a random number generator, or with some facsimile of one provided by an attacker?" And it certainly can't assert "nobody is allowed to do anything with this crypto secret except in ways that I, the author, approve of". These are two properties that often are provided in other environments that use crypto, and they're impossible in Javascript.




              Basically the problem is this:




              • Your clients don't trust your servers, so they want to add extra security code.

              • That security code is delivered by your servers (the ones they don't trust).


              Or alternatively,




              • Your clients don't trust SSL, so they want you use extra security code.

              • That security code is delivered via SSL.


              Note: Also, SHA-256 isn't suitable for this, since it's so easy to brute force unsalted non-iterated passwords. If you decide to do this anyway, look for an implementation of bcrypt, scrypt or PBKDF2.






              share|improve this answer















              No, there's no way to use browser JavaScript to improve password security. I highly recommend you read this article. In your case, the biggest problem is the chicken-egg problem:




              What's the "chicken-egg problem" with delivering Javascript cryptography?



              If you don't trust the network to deliver a password, or, worse, don't trust the server not to keep user secrets, you can't trust them to deliver security code. The same attacker who was sniffing passwords or reading diaries before you introduce crypto is simply hijacking crypto code after you do.




              [...]




              Why can't I use TLS/SSL to deliver the Javascript crypto code?



              You can. It's harder than it sounds, but you safely transmit Javascript crypto to a browser using SSL. The problem is, having established a secure channel with SSL, you no longer need Javascript cryptography; you have "real" cryptography.




              Which leads to this:




              The problem with running crypto code in Javascript is that practically any function that the crypto depends on could be overridden silently by any piece of content used to build the hosting page. Crypto security could be undone early in the process (by generating bogus random numbers, or by tampering with constants and parameters used by algorithms), or later (by spiriting key material back to an attacker), or --- in the most likely scenario --- by bypassing the crypto entirely.



              There is no reliable way for any piece of Javascript code to verify its execution environment. Javascript crypto code can't ask, "am I really dealing with a random number generator, or with some facsimile of one provided by an attacker?" And it certainly can't assert "nobody is allowed to do anything with this crypto secret except in ways that I, the author, approve of". These are two properties that often are provided in other environments that use crypto, and they're impossible in Javascript.




              Basically the problem is this:




              • Your clients don't trust your servers, so they want to add extra security code.

              • That security code is delivered by your servers (the ones they don't trust).


              Or alternatively,




              • Your clients don't trust SSL, so they want you use extra security code.

              • That security code is delivered via SSL.


              Note: Also, SHA-256 isn't suitable for this, since it's so easy to brute force unsalted non-iterated passwords. If you decide to do this anyway, look for an implementation of bcrypt, scrypt or PBKDF2.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Oct 4 '13 at 16:29

























              answered Aug 19 '13 at 22:14









              Brendan LongBrendan Long

              40.5k11115155




              40.5k11115155








              • 1





                This is not correct. The password security can be improved by hashing on the client side. It is also wrong that SHA-256 is unsuited as long as something like PBKDF2 is used on the server side. Thirdly, while the matasano article contains useful insight, the punch line is wrong since we now have browser apps that fundamentally change the chicken-and-egg issue.

                – user239558
                Oct 3 '13 at 23:14






              • 2





                You're right that PBKDF2 should be used on the client. The rage against client side javascript crypto assumes that the initial page and subsequent requests have the same security properties. That is obviously not true for browser apps where the initial page is installed separately and is static. It is also not true for any page with cache-forever semantics. In these cases, it is TOFU which is exactly the same as when installing a client side program. This can also be true in more complex setups where serving of static and dynamic pages are separated on the server.

                – user239558
                Oct 3 '13 at 23:31








              • 3





                It is legitimate to avoid system administrators to have access to user passwords, so hashing in the client side prevent DBAs or other IT professionals to see users passwords and try to reuse it to access other services/systems, since a lot of users repeat their passwords.

                – Yamada
                Apr 20 '16 at 12:27






              • 1





                @Xenland All you're doing is creating a new password which is "token + password". All of the original problems still apply. For example, an attacker can replace the JavaScript with code to send them the token + password.

                – Brendan Long
                Nov 16 '16 at 23:40






              • 1





                @Xenland The chicken and egg problem doesn't have anything to do with the requests you send. The problem is that your client is using JavaScript code that it downloaded over an insecure connection to do security work. The only way to safely send JavaScript to a web browser is to serve it over TLS, and once you do that, you don't need to do anything else because your connection is already secure. It doesn't matter what your protocol is if you're using JavaScript code that an attacker can just replace.

                – Brendan Long
                Nov 22 '16 at 14:13














              • 1





                This is not correct. The password security can be improved by hashing on the client side. It is also wrong that SHA-256 is unsuited as long as something like PBKDF2 is used on the server side. Thirdly, while the matasano article contains useful insight, the punch line is wrong since we now have browser apps that fundamentally change the chicken-and-egg issue.

                – user239558
                Oct 3 '13 at 23:14






              • 2





                You're right that PBKDF2 should be used on the client. The rage against client side javascript crypto assumes that the initial page and subsequent requests have the same security properties. That is obviously not true for browser apps where the initial page is installed separately and is static. It is also not true for any page with cache-forever semantics. In these cases, it is TOFU which is exactly the same as when installing a client side program. This can also be true in more complex setups where serving of static and dynamic pages are separated on the server.

                – user239558
                Oct 3 '13 at 23:31








              • 3





                It is legitimate to avoid system administrators to have access to user passwords, so hashing in the client side prevent DBAs or other IT professionals to see users passwords and try to reuse it to access other services/systems, since a lot of users repeat their passwords.

                – Yamada
                Apr 20 '16 at 12:27






              • 1





                @Xenland All you're doing is creating a new password which is "token + password". All of the original problems still apply. For example, an attacker can replace the JavaScript with code to send them the token + password.

                – Brendan Long
                Nov 16 '16 at 23:40






              • 1





                @Xenland The chicken and egg problem doesn't have anything to do with the requests you send. The problem is that your client is using JavaScript code that it downloaded over an insecure connection to do security work. The only way to safely send JavaScript to a web browser is to serve it over TLS, and once you do that, you don't need to do anything else because your connection is already secure. It doesn't matter what your protocol is if you're using JavaScript code that an attacker can just replace.

                – Brendan Long
                Nov 22 '16 at 14:13








              1




              1





              This is not correct. The password security can be improved by hashing on the client side. It is also wrong that SHA-256 is unsuited as long as something like PBKDF2 is used on the server side. Thirdly, while the matasano article contains useful insight, the punch line is wrong since we now have browser apps that fundamentally change the chicken-and-egg issue.

              – user239558
              Oct 3 '13 at 23:14





              This is not correct. The password security can be improved by hashing on the client side. It is also wrong that SHA-256 is unsuited as long as something like PBKDF2 is used on the server side. Thirdly, while the matasano article contains useful insight, the punch line is wrong since we now have browser apps that fundamentally change the chicken-and-egg issue.

              – user239558
              Oct 3 '13 at 23:14




              2




              2





              You're right that PBKDF2 should be used on the client. The rage against client side javascript crypto assumes that the initial page and subsequent requests have the same security properties. That is obviously not true for browser apps where the initial page is installed separately and is static. It is also not true for any page with cache-forever semantics. In these cases, it is TOFU which is exactly the same as when installing a client side program. This can also be true in more complex setups where serving of static and dynamic pages are separated on the server.

              – user239558
              Oct 3 '13 at 23:31







              You're right that PBKDF2 should be used on the client. The rage against client side javascript crypto assumes that the initial page and subsequent requests have the same security properties. That is obviously not true for browser apps where the initial page is installed separately and is static. It is also not true for any page with cache-forever semantics. In these cases, it is TOFU which is exactly the same as when installing a client side program. This can also be true in more complex setups where serving of static and dynamic pages are separated on the server.

              – user239558
              Oct 3 '13 at 23:31






              3




              3





              It is legitimate to avoid system administrators to have access to user passwords, so hashing in the client side prevent DBAs or other IT professionals to see users passwords and try to reuse it to access other services/systems, since a lot of users repeat their passwords.

              – Yamada
              Apr 20 '16 at 12:27





              It is legitimate to avoid system administrators to have access to user passwords, so hashing in the client side prevent DBAs or other IT professionals to see users passwords and try to reuse it to access other services/systems, since a lot of users repeat their passwords.

              – Yamada
              Apr 20 '16 at 12:27




              1




              1





              @Xenland All you're doing is creating a new password which is "token + password". All of the original problems still apply. For example, an attacker can replace the JavaScript with code to send them the token + password.

              – Brendan Long
              Nov 16 '16 at 23:40





              @Xenland All you're doing is creating a new password which is "token + password". All of the original problems still apply. For example, an attacker can replace the JavaScript with code to send them the token + password.

              – Brendan Long
              Nov 16 '16 at 23:40




              1




              1





              @Xenland The chicken and egg problem doesn't have anything to do with the requests you send. The problem is that your client is using JavaScript code that it downloaded over an insecure connection to do security work. The only way to safely send JavaScript to a web browser is to serve it over TLS, and once you do that, you don't need to do anything else because your connection is already secure. It doesn't matter what your protocol is if you're using JavaScript code that an attacker can just replace.

              – Brendan Long
              Nov 22 '16 at 14:13





              @Xenland The chicken and egg problem doesn't have anything to do with the requests you send. The problem is that your client is using JavaScript code that it downloaded over an insecure connection to do security work. The only way to safely send JavaScript to a web browser is to serve it over TLS, and once you do that, you don't need to do anything else because your connection is already secure. It doesn't matter what your protocol is if you're using JavaScript code that an attacker can just replace.

              – Brendan Long
              Nov 22 '16 at 14:13











              6














              I found this implementation very easy to use. Also has a generous BSD-style license:



              jsSHA: https://github.com/Caligatio/jsSHA



              I needed a quick way to get the hex-string representation of a SHA-256 hash. It only took 3 lines:



              var sha256 = new jsSHA('SHA-256', 'TEXT');
              sha256.update(some_string_variable_to_hash);
              var hash = sha256.getHash("HEX");





              share|improve this answer




























                6














                I found this implementation very easy to use. Also has a generous BSD-style license:



                jsSHA: https://github.com/Caligatio/jsSHA



                I needed a quick way to get the hex-string representation of a SHA-256 hash. It only took 3 lines:



                var sha256 = new jsSHA('SHA-256', 'TEXT');
                sha256.update(some_string_variable_to_hash);
                var hash = sha256.getHash("HEX");





                share|improve this answer


























                  6












                  6








                  6







                  I found this implementation very easy to use. Also has a generous BSD-style license:



                  jsSHA: https://github.com/Caligatio/jsSHA



                  I needed a quick way to get the hex-string representation of a SHA-256 hash. It only took 3 lines:



                  var sha256 = new jsSHA('SHA-256', 'TEXT');
                  sha256.update(some_string_variable_to_hash);
                  var hash = sha256.getHash("HEX");





                  share|improve this answer













                  I found this implementation very easy to use. Also has a generous BSD-style license:



                  jsSHA: https://github.com/Caligatio/jsSHA



                  I needed a quick way to get the hex-string representation of a SHA-256 hash. It only took 3 lines:



                  var sha256 = new jsSHA('SHA-256', 'TEXT');
                  sha256.update(some_string_variable_to_hash);
                  var hash = sha256.getHash("HEX");






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jun 2 '16 at 0:28









                  cobbzillacobbzilla

                  1,45211312




                  1,45211312























                      5














                      For those interested, this is code for creating SHA-256 hash using sjcl:



                      import sjcl from 'sjcl'

                      const myString = 'Hello'
                      const myBitArray = sjcl.hash.sha256.hash(myString)
                      const myHash = sjcl.codec.hex.fromBits(myBitArray)





                      share|improve this answer



















                      • 1





                        This should be incorporated in the accepted answer for those who want to use the solution there. (Heck, even their own docs don't have a snippet like this)

                        – MagicLegend
                        Oct 5 '18 at 16:05
















                      5














                      For those interested, this is code for creating SHA-256 hash using sjcl:



                      import sjcl from 'sjcl'

                      const myString = 'Hello'
                      const myBitArray = sjcl.hash.sha256.hash(myString)
                      const myHash = sjcl.codec.hex.fromBits(myBitArray)





                      share|improve this answer



















                      • 1





                        This should be incorporated in the accepted answer for those who want to use the solution there. (Heck, even their own docs don't have a snippet like this)

                        – MagicLegend
                        Oct 5 '18 at 16:05














                      5












                      5








                      5







                      For those interested, this is code for creating SHA-256 hash using sjcl:



                      import sjcl from 'sjcl'

                      const myString = 'Hello'
                      const myBitArray = sjcl.hash.sha256.hash(myString)
                      const myHash = sjcl.codec.hex.fromBits(myBitArray)





                      share|improve this answer













                      For those interested, this is code for creating SHA-256 hash using sjcl:



                      import sjcl from 'sjcl'

                      const myString = 'Hello'
                      const myBitArray = sjcl.hash.sha256.hash(myString)
                      const myHash = sjcl.codec.hex.fromBits(myBitArray)






                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Feb 12 '18 at 1:37









                      Danny SullivanDanny Sullivan

                      1,44921725




                      1,44921725








                      • 1





                        This should be incorporated in the accepted answer for those who want to use the solution there. (Heck, even their own docs don't have a snippet like this)

                        – MagicLegend
                        Oct 5 '18 at 16:05














                      • 1





                        This should be incorporated in the accepted answer for those who want to use the solution there. (Heck, even their own docs don't have a snippet like this)

                        – MagicLegend
                        Oct 5 '18 at 16:05








                      1




                      1





                      This should be incorporated in the accepted answer for those who want to use the solution there. (Heck, even their own docs don't have a snippet like this)

                      – MagicLegend
                      Oct 5 '18 at 16:05





                      This should be incorporated in the accepted answer for those who want to use the solution there. (Heck, even their own docs don't have a snippet like this)

                      – MagicLegend
                      Oct 5 '18 at 16:05











                      0














                      Besides the Stanford lib that tylerl mentioned. I found jsrsasign very useful (Github repo here:https://github.com/kjur/jsrsasign). I don't know how exactly trustworthy it is, but i've used its API of SHA256, Base64, RSA, x509 etc. and it works pretty well. In fact, it includes the Stanford lib as well.



                      If all you want to do is SHA256, jsrsasign might be a overkill. But if you have other needs in the related area, I feel it's a good fit.






                      share|improve this answer



















                      • 1





                        It is safer and faster to use developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

                        – Vitaly Zdanevich
                        Jan 30 at 8:29











                      • Agree, but to be fair,I answered this question in 2015 while mozilla's web crypto API specification was published Jan 2017

                        – Faraway
                        Feb 12 at 7:52
















                      0














                      Besides the Stanford lib that tylerl mentioned. I found jsrsasign very useful (Github repo here:https://github.com/kjur/jsrsasign). I don't know how exactly trustworthy it is, but i've used its API of SHA256, Base64, RSA, x509 etc. and it works pretty well. In fact, it includes the Stanford lib as well.



                      If all you want to do is SHA256, jsrsasign might be a overkill. But if you have other needs in the related area, I feel it's a good fit.






                      share|improve this answer



















                      • 1





                        It is safer and faster to use developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

                        – Vitaly Zdanevich
                        Jan 30 at 8:29











                      • Agree, but to be fair,I answered this question in 2015 while mozilla's web crypto API specification was published Jan 2017

                        – Faraway
                        Feb 12 at 7:52














                      0












                      0








                      0







                      Besides the Stanford lib that tylerl mentioned. I found jsrsasign very useful (Github repo here:https://github.com/kjur/jsrsasign). I don't know how exactly trustworthy it is, but i've used its API of SHA256, Base64, RSA, x509 etc. and it works pretty well. In fact, it includes the Stanford lib as well.



                      If all you want to do is SHA256, jsrsasign might be a overkill. But if you have other needs in the related area, I feel it's a good fit.






                      share|improve this answer













                      Besides the Stanford lib that tylerl mentioned. I found jsrsasign very useful (Github repo here:https://github.com/kjur/jsrsasign). I don't know how exactly trustworthy it is, but i've used its API of SHA256, Base64, RSA, x509 etc. and it works pretty well. In fact, it includes the Stanford lib as well.



                      If all you want to do is SHA256, jsrsasign might be a overkill. But if you have other needs in the related area, I feel it's a good fit.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Dec 11 '15 at 22:29









                      FarawayFaraway

                      4021721




                      4021721








                      • 1





                        It is safer and faster to use developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

                        – Vitaly Zdanevich
                        Jan 30 at 8:29











                      • Agree, but to be fair,I answered this question in 2015 while mozilla's web crypto API specification was published Jan 2017

                        – Faraway
                        Feb 12 at 7:52














                      • 1





                        It is safer and faster to use developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

                        – Vitaly Zdanevich
                        Jan 30 at 8:29











                      • Agree, but to be fair,I answered this question in 2015 while mozilla's web crypto API specification was published Jan 2017

                        – Faraway
                        Feb 12 at 7:52








                      1




                      1





                      It is safer and faster to use developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

                      – Vitaly Zdanevich
                      Jan 30 at 8:29





                      It is safer and faster to use developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

                      – Vitaly Zdanevich
                      Jan 30 at 8:29













                      Agree, but to be fair,I answered this question in 2015 while mozilla's web crypto API specification was published Jan 2017

                      – Faraway
                      Feb 12 at 7:52





                      Agree, but to be fair,I answered this question in 2015 while mozilla's web crypto API specification was published Jan 2017

                      – Faraway
                      Feb 12 at 7:52


















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f18338890%2fare-there-any-sha-256-javascript-implementations-that-are-generally-considered-t%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Monofisismo

                      Angular Downloading a file using contenturl with Basic Authentication

                      Olmecas