@sskmy1024y/react-native-hash
Version:
A hashing library for react-native
128 lines (109 loc) • 2.98 kB
JavaScript
/* eslint linebreak-style: ["error", "windows"] */
/* eslint-disable no-use-before-define */
import Base from './Base.js';
import Utf8 from './Utf8.js';
/**
* HMAC algorithm.
*/
export default class HMAC extends Base {
/**
* Initializes a newly created HMAC.
*
* @param {Hasher} SubHasher The hash algorithm to use.
* @param {WordArray|string} key The secret key.
*
* @example
*
* var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
*/
constructor(SubHasher, key) {
super();
const hasher = new SubHasher();
this._hasher = hasher;
// Convert string to WordArray, else assume WordArray already
let _key = key;
if (typeof _key === 'string') {
_key = Utf8.parse(_key);
}
// Shortcuts
const hasherBlockSize = hasher.blockSize;
const hasherBlockSizeBytes = hasherBlockSize * 4;
// Allow arbitrary length keys
if (_key.sigBytes > hasherBlockSizeBytes) {
_key = hasher.finalize(key);
}
// Clamp excess bits
_key.clamp();
// Clone key for inner and outer pads
const oKey = _key.clone();
this._oKey = oKey;
const iKey = _key.clone();
this._iKey = iKey;
// Shortcuts
const oKeyWords = oKey.words;
const iKeyWords = iKey.words;
// XOR keys with pad constants
for (let i = 0; i < hasherBlockSize; i += 1) {
oKeyWords[i] ^= 0x5c5c5c5c;
iKeyWords[i] ^= 0x36363636;
}
oKey.sigBytes = hasherBlockSizeBytes;
iKey.sigBytes = hasherBlockSizeBytes;
// Set initial values
this.reset();
}
/**
* Resets this HMAC to its initial state.
*
* @example
*
* hmacHasher.reset();
*/
reset() {
// Shortcut
const hasher = this._hasher;
// Reset
hasher.reset();
hasher.update(this._iKey);
}
/**
* Updates this HMAC with a message.
*
* @param {WordArray|string} messageUpdate The message to append.
*
* @return {HMAC} This HMAC instance.
*
* @example
*
* hmacHasher.update('message');
* hmacHasher.update(wordArray);
*/
update(messageUpdate) {
this._hasher.update(messageUpdate);
// Chainable
return this;
}
/**
* Finalizes the HMAC computation.
* Note that the finalize operation is effectively a destructive, read-once operation.
*
* @param {WordArray|string} messageUpdate (Optional) A final message update.
*
* @return {WordArray} The HMAC.
*
* @example
*
* var hmac = hmacHasher.finalize();
* var hmac = hmacHasher.finalize('message');
* var hmac = hmacHasher.finalize(wordArray);
*/
finalize(messageUpdate) {
// Shortcut
const hasher = this._hasher;
// Compute HMAC
const innerHash = hasher.finalize(messageUpdate);
hasher.reset();
const hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
return hmac;
}
}