Skip to content
Advertisement

Different results trying to port SHA-1 digest from Python to browser JavaScript

Main question

I have the following short piece of legacy code that I am trying to port from Python (with just standard lib) to JavaScript – from the name of the methods I assume it creates a SHA-1 digest of the abc string

JavaScript

I searched for how to do that in the browser in JS and found the following code in the Mozilla documentation

JavaScript

the problem is, they yield two completely different results, and I have no idea why:

  • cc47e3c0aa0c2984454476d061108c0b110177ae – Python
  • a9993e364706816aba3e25717850c26c9cd0d89d – JavaScript

I tried comparing the bytes of b"abc" with what new TextEncoder().encode('abc') returns and they are exactly the same: 0x61 0x62 0x63, so the problem lies somewhere else and I have no idea where.

I need the JavaScript code to return what the Python code returns. Any ideas?


Additionally

My final goal is to actually port this code (note the b"hello" instead of None):

JavaScript

so if you have an idea on that one too – I would hugely appreciate it!

Advertisement

Answer

The Python code calculates a SHA1 based HMAC. The JavaScript code on the other hand computes a SHA-1 hash. An HMAC needs a key in addition to the data, while a cryptographic hash function works without a key.

The first Python code uses the key abc and an empty message. The posted result for the HMAC is hex encoded:

JavaScript

The second Python code uses the same key and the message hello. The result for the HMAC is hex encoded:

JavaScript

The Java code determines the SHA-1 hash for abc. The result is

JavaScript

So all results are correct, but are generated with different input data or algorithms.


The calculation of the HMAC can be implemented with the browser native WebCrypto-API as follows:

JavaScript

and provides the same result as the two Python codes.

A remark to SHA-1: Although HMAC/SHA-1 is considered to be secure (contrary to SHA-1), there are arguments to switch to SHA-256, see here.


The WebCrypto API is a bit cumbersome. A functionally identical implementation with CryptoJS, the library mentioned in the comment by Maurice Meyer, is simpler and looks like this:

JavaScript
JavaScript

but requires CryptoJS as external dependency.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement