pbkdf2.js 4.8 KB

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