Implementation of HMAC algorithm in javascript with plain javascript strings, using SHA1 as underline hash functon.

Downloads in past


200.1.15 years ago6 years agoMinified + gzip package size for hmac_sha1 in KB


HmacSha1 Build Status

In order to utilise many free APIs, communication with server needs authentication checks for the application that access it and for user in which name application makes the request. Lot's of API's still require OAuth 1.0a, where HMACSHA1 is significant part, for that purpose.
This implementation uses only plain javascript strings so that is what it expects to pass it. Although sha1 function from nodes core crypto lib which this implementation depends uppon does use Buffers. Also, this hmac uses ES6 String.fromCodePoint(..) to correctly map code points of higher unicode plains.


It seems that sha1 functions by default return string of 40 hex chars that is just, well hex string representation of underlying data, not the data itself. Meaning if sha1 produces data stream of, for example:
0100 1110 which if represent as hex string is "4e"
, it returns "4e". By default.
But we cant directly use that in our HMAC alghorithm since "4e" is different stream of data:
0011 0110 0110 1001 its hex is "3465"
So we cant use different data then what sha1 has really produced, what we can do is this hex string representation ("4e") of underlying data convert to it's character counterpart:
0100 1110 <-- ("4e") becomes char ("N")--> 0100 1110.
In this context it's good to think that sha1 spits out hex string by treating every 4 bits of underlying data, a nibble. And that we compress that string by mapping 8 bits of data to their string representation.
That is char "N" is exact mapping of data that sha1 produced it is not hex string representation of data. If we have 40 hex chars that means 40 bytes and by SHA1 rfc, sha1 produces 20 byte data. By doing this conversion we get that 20 byte data and all the time we are using strings with same effect if we were using ArrayBuffer/Buffer, at least that's the idea



npm install hmac_sha1


The digest function of an HmacSha1 instance receives three arguments, key , baseString and optional enc-oding.


In this example the key and message (baseString) for testing are used from twitter api example
var baseStr = "POST&"

var key = "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw&LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE";

hmacSha1 = new HmacSha1();

hmacSha1.digest(key, baseStr) //   b679c0af18f4e9c587ab8e200acd4e48a93f8cb6


Wiki example:
In most cases you are good with default usage:
hmacSha1 = new HmacSha1(); // no result encoding specified, defaults to 'hex'
hmacSha1.digest("key", "The quick brown fox jumps over the lazy dog") // de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9


If you want result in base64:
hmacSha1 = new HmacSha1('base64'); // put format in constructor call
hmacSha1.digest("key", "The quick brown fox jumps over the lazy dog"); // 3nybhbi3iqa8ino29wqQcBydtNk=


You can use 'utf8' encoding:
hmacSha1 = new HmacSha1('base64');
hmacSha1.digest('key', 'The quick brown fox jumps over the lazy dog¶汉字💩', 'utf8'); // LYsDRV73mlS0VAkq5WSr915Nnu4=                                                                            
But, when you are using 'utf8' encoding your key must be in ascii code. Basicaly it means that only your baseString (message) is allowed to have non ascii chars. If that's not the case function throws an error:
hmacSha1 = new HmacSha1('base64');
hmac.digest('key¶汉字','The quick brown fox jumps over the lazy dog¶汉字💩', 'utf8' ) // Error 

hmac.digest('key','The quick brown fox jumps over the lazy dog¶汉字💩', 'utf8' ) // LYsDRV73mlS0VAkq5WSr915Nnu4=
If key or the massage contain backward slash the JS engine will interpret it as a escape sequence character "\\", or in other words it will ignore it (depending of what subsequent char is). So the funcion produces digest like there is no escape sequence character present.
hmacSha1 = new HmacSha1();
hmacSha1.digest("ke\y", "So\me mess\age") // b93ddca7f62b74ab43cb23e0581a05d50a27b9e9
// Result is like we passed "key" and "Some message"

So we need to escape each backward slash like so:
hmacSha1 = new HmacSha1();
hmacSha1.digest("ke\\y", "So\\me mess\\age") // 136d22549e17ee6665dc398bbba43c5e912e3e92
// Result is like we passed "ke\y" and "So\me mess\age"
A reference point so you can see it complies with other implementations of HMACSHA1. Or fire up HMAC from node's crypto lib.
Don't feel obliged to donate but any donation is greatly appreciated.
Don't feel obliged to donate but any donation is greatly appreciated. paypal