pbkdf2.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import {
  2. Base,
  3. WordArray,
  4. } from './core.js';
  5. import { SHA1Algo } from './sha1.js';
  6. import { HMAC } from './hmac.js';
  7. /**
  8. * Password-Based Key Derivation Function 2 algorithm.
  9. */
  10. export class PBKDF2Algo extends Base {
  11. /**
  12. * Initializes a newly created key derivation function.
  13. *
  14. * @param {Object} cfg (Optional) The configuration options to use for the derivation.
  15. *
  16. * @example
  17. *
  18. * const kdf = CryptoJS.algo.PBKDF2.create();
  19. * const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
  20. * const kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 });
  21. */
  22. constructor(cfg) {
  23. super();
  24. /**
  25. * Configuration options.
  26. *
  27. * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
  28. * @property {Hasher} hasher The hasher to use. Default: SHA1
  29. * @property {number} iterations The number of iterations to perform. Default: 1
  30. */
  31. this.cfg = Object.assign(
  32. new Base(),
  33. {
  34. keySize: 128 / 32,
  35. hasher: SHA1Algo,
  36. iterations: 1,
  37. },
  38. cfg,
  39. );
  40. }
  41. /**
  42. * Computes the Password-Based Key Derivation Function 2.
  43. *
  44. * @param {WordArray|string} password The password.
  45. * @param {WordArray|string} salt A salt.
  46. *
  47. * @return {WordArray} The derived key.
  48. *
  49. * @example
  50. *
  51. * const key = kdf.compute(password, salt);
  52. */
  53. compute(password, salt) {
  54. // Shortcut
  55. const { cfg } = this;
  56. // Init HMAC
  57. const hmac = HMAC.create(cfg.hasher, password);
  58. // Initial values
  59. const derivedKey = WordArray.create();
  60. const blockIndex = WordArray.create([0x00000001]);
  61. // Shortcuts
  62. const derivedKeyWords = derivedKey.words;
  63. const blockIndexWords = blockIndex.words;
  64. const { keySize, iterations } = cfg;
  65. // Generate key
  66. while (derivedKeyWords.length < keySize) {
  67. const block = hmac.update(salt).finalize(blockIndex);
  68. hmac.reset();
  69. // Shortcuts
  70. const blockWords = block.words;
  71. const blockWordsLength = blockWords.length;
  72. // Iterations
  73. let intermediate = block;
  74. for (let i = 1; i < iterations; i += 1) {
  75. intermediate = hmac.finalize(intermediate);
  76. hmac.reset();
  77. // Shortcut
  78. const intermediateWords = intermediate.words;
  79. // XOR intermediate with block
  80. for (let j = 0; j < blockWordsLength; j += 1) {
  81. blockWords[j] ^= intermediateWords[j];
  82. }
  83. }
  84. derivedKey.concat(block);
  85. blockIndexWords[0] += 1;
  86. }
  87. derivedKey.sigBytes = keySize * 4;
  88. return derivedKey;
  89. }
  90. }
  91. /**
  92. * Computes the Password-Based Key Derivation Function 2.
  93. *
  94. * @param {WordArray|string} password The password.
  95. * @param {WordArray|string} salt A salt.
  96. * @param {Object} cfg (Optional) The configuration options to use for this computation.
  97. *
  98. * @return {WordArray} The derived key.
  99. *
  100. * @static
  101. *
  102. * @example
  103. *
  104. * var key = CryptoJS.PBKDF2(password, salt);
  105. * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
  106. * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
  107. */
  108. export const PBKDF2 = (password, salt, cfg) => PBKDF2Algo.create(cfg).compute(password, salt);