pbkdf2.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. ;(function (root, factory, undef) {
  2. if (typeof exports === "object") {
  3. // CommonJS
  4. module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
  5. }
  6. else if (typeof define === "function" && define.amd) {
  7. // AMD
  8. define(["./core", "./sha1", "./hmac"], factory);
  9. }
  10. else {
  11. // Global (browser)
  12. factory(root.CryptoJS);
  13. }
  14. }(this, function (CryptoJS) {
  15. (function () {
  16. // Shortcuts
  17. var C = CryptoJS;
  18. var C_lib = C.lib;
  19. var Base = C_lib.Base;
  20. var WordArray = C_lib.WordArray;
  21. var C_algo = C.algo;
  22. var SHA1 = C_algo.SHA1;
  23. var HMAC = C_algo.HMAC;
  24. /**
  25. * Password-Based Key Derivation Function 2 algorithm.
  26. */
  27. var PBKDF2 = C_algo.PBKDF2 = Base.extend({
  28. /**
  29. * Configuration options.
  30. *
  31. * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
  32. * @property {Hasher} hasher The hasher to use. Default: SHA1
  33. * @property {number} iterations The number of iterations to perform. Default: 1
  34. */
  35. cfg: Base.extend({
  36. keySize: 128/32,
  37. hasher: SHA1,
  38. iterations: 1
  39. }),
  40. /**
  41. * Initializes a newly created key derivation function.
  42. *
  43. * @param {Object} cfg (Optional) The configuration options to use for the derivation.
  44. *
  45. * @example
  46. *
  47. * var kdf = CryptoJS.algo.PBKDF2.create();
  48. * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
  49. * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 });
  50. */
  51. init: function (cfg) {
  52. this.cfg = this.cfg.extend(cfg);
  53. },
  54. /**
  55. * Computes the Password-Based Key Derivation Function 2.
  56. *
  57. * @param {WordArray|string} password The password.
  58. * @param {WordArray|string} salt A salt.
  59. *
  60. * @return {WordArray} The derived key.
  61. *
  62. * @example
  63. *
  64. * var key = kdf.compute(password, salt);
  65. */
  66. compute: function (password, salt) {
  67. // Shortcut
  68. var cfg = this.cfg;
  69. // Init HMAC
  70. var hmac = HMAC.create(cfg.hasher, password);
  71. // Initial values
  72. var derivedKey = WordArray.create();
  73. var blockIndex = WordArray.create([0x00000001]);
  74. // Shortcuts
  75. var derivedKeyWords = derivedKey.words;
  76. var blockIndexWords = blockIndex.words;
  77. var keySize = cfg.keySize;
  78. var iterations = cfg.iterations;
  79. // Generate key
  80. while (derivedKeyWords.length < keySize) {
  81. var block = hmac.update(salt).finalize(blockIndex);
  82. hmac.reset();
  83. // Shortcuts
  84. var blockWords = block.words;
  85. var blockWordsLength = blockWords.length;
  86. // Iterations
  87. var intermediate = block;
  88. for (var i = 1; i < iterations; i++) {
  89. intermediate = hmac.finalize(intermediate);
  90. hmac.reset();
  91. // Shortcut
  92. var intermediateWords = intermediate.words;
  93. // XOR intermediate with block
  94. for (var j = 0; j < blockWordsLength; j++) {
  95. blockWords[j] ^= intermediateWords[j];
  96. }
  97. }
  98. derivedKey.concat(block);
  99. blockIndexWords[0]++;
  100. }
  101. derivedKey.sigBytes = keySize * 4;
  102. return derivedKey;
  103. }
  104. });
  105. /**
  106. * Computes the Password-Based Key Derivation Function 2.
  107. *
  108. * @param {WordArray|string} password The password.
  109. * @param {WordArray|string} salt A salt.
  110. * @param {Object} cfg (Optional) The configuration options to use for this computation.
  111. *
  112. * @return {WordArray} The derived key.
  113. *
  114. * @static
  115. *
  116. * @example
  117. *
  118. * var key = CryptoJS.PBKDF2(password, salt);
  119. * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
  120. * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
  121. */
  122. C.PBKDF2 = function (password, salt, cfg) {
  123. return PBKDF2.create(cfg).compute(password, salt);
  124. };
  125. }());
  126. return CryptoJS.PBKDF2;
  127. }));