123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- // Copyright 2011 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @fileoverview Implementation of HMAC in JavaScript.
- *
- * Usage:
- * var hmac = new goog.crypt.Hmac(new goog.crypt.sha1(), key, 64);
- * var digest = hmac.getHmac(bytes);
- *
- * @author benyu@google.com (Jige Yu) - port to closure
- */
- goog.provide('goog.crypt.Hmac');
- goog.require('goog.crypt.Hash');
- /**
- * @constructor
- * @param {!goog.crypt.Hash} hasher An object to serve as a hash function.
- * @param {Array<number>} key The secret key to use to calculate the hmac.
- * Should be an array of not more than {@code blockSize} integers in
- {0, 255}.
- * @param {number=} opt_blockSize Optional. The block size {@code hasher} uses.
- * If not specified, uses the block size from the hasher, or 16 if it is
- * not specified.
- * @extends {goog.crypt.Hash}
- * @final
- * @struct
- */
- goog.crypt.Hmac = function(hasher, key, opt_blockSize) {
- goog.crypt.Hmac.base(this, 'constructor');
- /**
- * The underlying hasher to calculate hash.
- *
- * @type {!goog.crypt.Hash}
- * @private
- */
- this.hasher_ = hasher;
- this.blockSize = opt_blockSize || hasher.blockSize || 16;
- /**
- * The outer padding array of hmac
- *
- * @type {!Array<number>}
- * @private
- */
- this.keyO_ = new Array(this.blockSize);
- /**
- * The inner padding array of hmac
- *
- * @type {!Array<number>}
- * @private
- */
- this.keyI_ = new Array(this.blockSize);
- this.initialize_(key);
- };
- goog.inherits(goog.crypt.Hmac, goog.crypt.Hash);
- /**
- * Outer padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC
- *
- * @type {number}
- * @private
- */
- goog.crypt.Hmac.OPAD_ = 0x5c;
- /**
- * Inner padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC
- *
- * @type {number}
- * @private
- */
- goog.crypt.Hmac.IPAD_ = 0x36;
- /**
- * Initializes Hmac by precalculating the inner and outer paddings.
- *
- * @param {Array<number>} key The secret key to use to calculate the hmac.
- * Should be an array of not more than {@code blockSize} integers in
- {0, 255}.
- * @private
- */
- goog.crypt.Hmac.prototype.initialize_ = function(key) {
- if (key.length > this.blockSize) {
- this.hasher_.update(key);
- key = this.hasher_.digest();
- this.hasher_.reset();
- }
- // Precalculate padded and xor'd keys.
- var keyByte;
- for (var i = 0; i < this.blockSize; i++) {
- if (i < key.length) {
- keyByte = key[i];
- } else {
- keyByte = 0;
- }
- this.keyO_[i] = keyByte ^ goog.crypt.Hmac.OPAD_;
- this.keyI_[i] = keyByte ^ goog.crypt.Hmac.IPAD_;
- }
- // Be ready for an immediate update.
- this.hasher_.update(this.keyI_);
- };
- /** @override */
- goog.crypt.Hmac.prototype.reset = function() {
- this.hasher_.reset();
- this.hasher_.update(this.keyI_);
- };
- /** @override */
- goog.crypt.Hmac.prototype.update = function(bytes, opt_length) {
- this.hasher_.update(bytes, opt_length);
- };
- /** @override */
- goog.crypt.Hmac.prototype.digest = function() {
- var temp = this.hasher_.digest();
- this.hasher_.reset();
- this.hasher_.update(this.keyO_);
- this.hasher_.update(temp);
- return this.hasher_.digest();
- };
- /**
- * Calculates an HMAC for a given message.
- *
- * @param {Array<number>|Uint8Array|string} message Data to Hmac.
- * @return {!Array<number>} the digest of the given message.
- */
- goog.crypt.Hmac.prototype.getHmac = function(message) {
- this.reset();
- this.update(message);
- return this.digest();
- };
|