48

I'd like to be able to create unique tokens* for users based on a hashed string. I know I could, for example, use a md5() library but as the purpose is not cryptographic I was wondering if there was anything I could use "out of the box." Are there any one-way hashing functions available in native JavaScript?

*I realize these won't be strictly unique. I'm ok with a small chance of hashing collision.

buley
  • 28,032
  • 17
  • 85
  • 106
  • 1
    you may like this question - http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript – Anurag Feb 24 '11 at 22:55
  • Yup, like that a lot. I need a one way hash vs. GUIDs. I have a a large string and want to hash it into a smaller string the same way every time. md5 works for that purposes but seems like overkill. – buley Feb 24 '11 at 23:08

4 Answers4

19

In 2020, there is a native API:

SubtleCrypto.digest()

https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest

example:

crypto.subtle
  .digest("SHA-256", new TextEncoder().encode("hello"))
  .then(console.log);

hex string conversion:

const digest = async ({ algorithm = "SHA-256", message }) =>
  Array.prototype.map
    .call(
      new Uint8Array(
        await crypto.subtle.digest(algorithm, new TextEncoder().encode(message))
      ),
      (x) => ("0" + x.toString(16)).slice(-2)
    )
    .join("");

digest({message: "hello"}).then(console.log)
Weihang Jian
  • 7,826
  • 4
  • 44
  • 55
  • The SubtleCrypto API requires a TLS-enabled website, however. Are there any options that lack this constraint? – Drowsy Apr 13 '22 at 13:46
  • Note: all browsers actually supported this by mid 2015 already; except Edge, which didn't have SHA-1 support until Jan 2020 with "New Edge" and the switch to Chromium. Node got support in 2020. – Darryl Noakes Mar 28 '23 at 12:44
11

JavaScript does not have native hashing, but there are many libraries.

I recommend crypto-js: https://code.google.com/p/crypto-js/

For example, to use SHA1, you simply:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/sha1.js"></script>
<script>
    var hash = CryptoJS.SHA1("Message");
</script>
Caerulius
  • 425
  • 4
  • 21
Tero Niemi
  • 1,057
  • 11
  • 13
6

Nothing is available in native JavaScript. You could use something like Murmurhash. There's a JavaScript implementation here: https://github.com/garycourt/murmurhash-js. I haven't used it though so can't vouch for it.

Update: now there are multiple Murmurhash3 implementations available in JavaScript. However, many of them have problems encoding strings to bytes and can produce different results compared to the reference C++ implementation. You can read an analysis on this here, the murmurhash3js-revisited library implements all three variants of the function and conforms to the reference.

Alex Ciminian
  • 11,398
  • 15
  • 60
  • 94
Tim Down
  • 318,141
  • 75
  • 454
  • 536
5

Over the horizon, this may be possible with the currently experimental Web Crypto API

https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API

https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto

Granted, at the time of this writing it is unrealistic to use in a production environment and will likely be a moving target. However, come 5 years who knows?

Adam Grant
  • 12,477
  • 10
  • 58
  • 65
  • Personally, I'd really like to explore using this to share code between sites using localStorage (there's a hack allowing to use this cross domain). Crypto signing could protect against a site masking evil code as the saved version of jQuery, for example. CDN does this now, but requires an HTTP request. – Adam Grant May 24 '16 at 17:30