UNPKG

blocktrail-sdk

Version:

BlockTrail's Developer Friendly API binding for NodeJS

143 lines (107 loc) 3.69 kB
function hmac_constructor ( options ) { options = options || {}; if ( !options.hash ) throw new SyntaxError("option 'hash' is required"); if ( !options.hash.HASH_SIZE ) throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function"); this.hash = options.hash; this.BLOCK_SIZE = this.hash.BLOCK_SIZE; this.HMAC_SIZE = this.hash.HASH_SIZE; this.key = null; this.verify = null; this.result = null; if ( options.password !== undefined || options.verify !== undefined ) this.reset(options); return this; } function _hmac_key ( hash, password ) { if ( is_buffer(password) ) password = new Uint8Array(password); if ( is_string(password) ) password = string_to_bytes(password); if ( !is_bytes(password) ) throw new TypeError("password isn't of expected type"); var key = new Uint8Array( hash.BLOCK_SIZE ); if ( password.length > hash.BLOCK_SIZE ) { key.set( hash.reset().process(password).finish().result ); } else { key.set(password); } return key; } function _hmac_init_verify ( verify ) { if ( is_buffer(verify) || is_bytes(verify) ) { verify = new Uint8Array(verify); } else if ( is_string(verify) ) { verify = string_to_bytes(verify); } else { throw new TypeError("verify tag isn't of expected type"); } if ( verify.length !== this.HMAC_SIZE ) throw new IllegalArgumentError("illegal verification tag size"); this.verify = verify; } function hmac_reset ( options ) { options = options || {}; var password = options.password; if ( this.key === null && !is_string(password) && !password ) throw new IllegalStateError("no key is associated with the instance"); this.result = null; this.hash.reset(); if ( password || is_string(password) ) this.key = _hmac_key( this.hash, password ); var ipad = new Uint8Array(this.key); for ( var i = 0; i < ipad.length; ++i ) ipad[i] ^= 0x36; this.hash.process(ipad); var verify = options.verify; if ( verify !== undefined ) { _hmac_init_verify.call( this, verify ); } else { this.verify = null; } return this; } function hmac_process ( data ) { if ( this.key === null ) throw new IllegalStateError("no key is associated with the instance"); if ( this.result !== null ) throw new IllegalStateError("state must be reset before processing new data"); this.hash.process(data); return this; } function hmac_finish () { if ( this.key === null ) throw new IllegalStateError("no key is associated with the instance"); if ( this.result !== null ) throw new IllegalStateError("state must be reset before processing new data"); var inner_result = this.hash.finish().result; var opad = new Uint8Array(this.key); for ( var i = 0; i < opad.length; ++i ) opad[i] ^= 0x5c; var verify = this.verify; var result = this.hash.reset().process(opad).process(inner_result).finish().result; if ( verify ) { if ( verify.length === result.length ) { var diff = 0; for ( var i = 0; i < verify.length; i++ ) { diff |= ( verify[i] ^ result[i] ); } this.result = !diff; } else { this.result = false; } } else { this.result = result; } return this; } var hmac_prototype = hmac_constructor.prototype; hmac_prototype.reset = hmac_reset; hmac_prototype.process = hmac_process; hmac_prototype.finish = hmac_finish;