hmac.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright 2011 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Implementation of HMAC in JavaScript.
  16. *
  17. * Usage:
  18. * var hmac = new goog.crypt.Hmac(new goog.crypt.sha1(), key, 64);
  19. * var digest = hmac.getHmac(bytes);
  20. *
  21. * @author benyu@google.com (Jige Yu) - port to closure
  22. */
  23. goog.provide('goog.crypt.Hmac');
  24. goog.require('goog.crypt.Hash');
  25. /**
  26. * @constructor
  27. * @param {!goog.crypt.Hash} hasher An object to serve as a hash function.
  28. * @param {Array<number>} key The secret key to use to calculate the hmac.
  29. * Should be an array of not more than {@code blockSize} integers in
  30. {0, 255}.
  31. * @param {number=} opt_blockSize Optional. The block size {@code hasher} uses.
  32. * If not specified, uses the block size from the hasher, or 16 if it is
  33. * not specified.
  34. * @extends {goog.crypt.Hash}
  35. * @final
  36. * @struct
  37. */
  38. goog.crypt.Hmac = function(hasher, key, opt_blockSize) {
  39. goog.crypt.Hmac.base(this, 'constructor');
  40. /**
  41. * The underlying hasher to calculate hash.
  42. *
  43. * @type {!goog.crypt.Hash}
  44. * @private
  45. */
  46. this.hasher_ = hasher;
  47. this.blockSize = opt_blockSize || hasher.blockSize || 16;
  48. /**
  49. * The outer padding array of hmac
  50. *
  51. * @type {!Array<number>}
  52. * @private
  53. */
  54. this.keyO_ = new Array(this.blockSize);
  55. /**
  56. * The inner padding array of hmac
  57. *
  58. * @type {!Array<number>}
  59. * @private
  60. */
  61. this.keyI_ = new Array(this.blockSize);
  62. this.initialize_(key);
  63. };
  64. goog.inherits(goog.crypt.Hmac, goog.crypt.Hash);
  65. /**
  66. * Outer padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC
  67. *
  68. * @type {number}
  69. * @private
  70. */
  71. goog.crypt.Hmac.OPAD_ = 0x5c;
  72. /**
  73. * Inner padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC
  74. *
  75. * @type {number}
  76. * @private
  77. */
  78. goog.crypt.Hmac.IPAD_ = 0x36;
  79. /**
  80. * Initializes Hmac by precalculating the inner and outer paddings.
  81. *
  82. * @param {Array<number>} key The secret key to use to calculate the hmac.
  83. * Should be an array of not more than {@code blockSize} integers in
  84. {0, 255}.
  85. * @private
  86. */
  87. goog.crypt.Hmac.prototype.initialize_ = function(key) {
  88. if (key.length > this.blockSize) {
  89. this.hasher_.update(key);
  90. key = this.hasher_.digest();
  91. this.hasher_.reset();
  92. }
  93. // Precalculate padded and xor'd keys.
  94. var keyByte;
  95. for (var i = 0; i < this.blockSize; i++) {
  96. if (i < key.length) {
  97. keyByte = key[i];
  98. } else {
  99. keyByte = 0;
  100. }
  101. this.keyO_[i] = keyByte ^ goog.crypt.Hmac.OPAD_;
  102. this.keyI_[i] = keyByte ^ goog.crypt.Hmac.IPAD_;
  103. }
  104. // Be ready for an immediate update.
  105. this.hasher_.update(this.keyI_);
  106. };
  107. /** @override */
  108. goog.crypt.Hmac.prototype.reset = function() {
  109. this.hasher_.reset();
  110. this.hasher_.update(this.keyI_);
  111. };
  112. /** @override */
  113. goog.crypt.Hmac.prototype.update = function(bytes, opt_length) {
  114. this.hasher_.update(bytes, opt_length);
  115. };
  116. /** @override */
  117. goog.crypt.Hmac.prototype.digest = function() {
  118. var temp = this.hasher_.digest();
  119. this.hasher_.reset();
  120. this.hasher_.update(this.keyO_);
  121. this.hasher_.update(temp);
  122. return this.hasher_.digest();
  123. };
  124. /**
  125. * Calculates an HMAC for a given message.
  126. *
  127. * @param {Array<number>|Uint8Array|string} message Data to Hmac.
  128. * @return {!Array<number>} the digest of the given message.
  129. */
  130. goog.crypt.Hmac.prototype.getHmac = function(message) {
  131. this.reset();
  132. this.update(message);
  133. return this.digest();
  134. };