| 'use strict'; |
| |
| var utils = require('./utils'); |
| var assert = require('minimalistic-assert'); |
| |
| function Hmac(hash, key, enc) { |
| if (!(this instanceof Hmac)) |
| return new Hmac(hash, key, enc); |
| this.Hash = hash; |
| this.blockSize = hash.blockSize / 8; |
| this.outSize = hash.outSize / 8; |
| this.inner = null; |
| this.outer = null; |
| |
| this._init(utils.toArray(key, enc)); |
| } |
| module.exports = Hmac; |
| |
| Hmac.prototype._init = function init(key) { |
| // Shorten key, if needed |
| if (key.length > this.blockSize) |
| key = new this.Hash().update(key).digest(); |
| assert(key.length <= this.blockSize); |
| |
| // Add padding to key |
| for (var i = key.length; i < this.blockSize; i++) |
| key.push(0); |
| |
| for (i = 0; i < key.length; i++) |
| key[i] ^= 0x36; |
| this.inner = new this.Hash().update(key); |
| |
| // 0x36 ^ 0x5c = 0x6a |
| for (i = 0; i < key.length; i++) |
| key[i] ^= 0x6a; |
| this.outer = new this.Hash().update(key); |
| }; |
| |
| Hmac.prototype.update = function update(msg, enc) { |
| this.inner.update(msg, enc); |
| return this; |
| }; |
| |
| Hmac.prototype.digest = function digest(enc) { |
| this.outer.update(this.inner.digest()); |
| return this.outer.digest(enc); |
| }; |