evpkdf.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import {
  2. Base,
  3. WordArray,
  4. } from './core.js';
  5. import { MD5Algo } from './md5.js';
  6. /**
  7. * This key derivation function is meant to conform with EVP_BytesToKey.
  8. * www.openssl.org/docs/crypto/EVP_BytesToKey.html
  9. */
  10. export class EvpKDFAlgo 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.EvpKDF.create();
  19. * const kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
  20. * const kdf = CryptoJS.algo.EvpKDF.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 hash algorithm to use. Default: MD5
  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: MD5Algo,
  36. iterations: 1,
  37. },
  38. cfg,
  39. );
  40. }
  41. /**
  42. * Derives a key from a password.
  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. let block;
  55. // Shortcut
  56. const { cfg } = this;
  57. // Init hasher
  58. const hasher = cfg.hasher.create();
  59. // Initial values
  60. const derivedKey = WordArray.create();
  61. // Shortcuts
  62. const derivedKeyWords = derivedKey.words;
  63. const { keySize, iterations } = cfg;
  64. // Generate key
  65. while (derivedKeyWords.length < keySize) {
  66. if (block) {
  67. hasher.update(block);
  68. }
  69. block = hasher.update(password).finalize(salt);
  70. hasher.reset();
  71. // Iterations
  72. for (let i = 1; i < iterations; i += 1) {
  73. block = hasher.finalize(block);
  74. hasher.reset();
  75. }
  76. derivedKey.concat(block);
  77. }
  78. derivedKey.sigBytes = keySize * 4;
  79. return derivedKey;
  80. }
  81. }
  82. /**
  83. * Derives a key from a password.
  84. *
  85. * @param {WordArray|string} password The password.
  86. * @param {WordArray|string} salt A salt.
  87. * @param {Object} cfg (Optional) The configuration options to use for this computation.
  88. *
  89. * @return {WordArray} The derived key.
  90. *
  91. * @static
  92. *
  93. * @example
  94. *
  95. * var key = CryptoJS.EvpKDF(password, salt);
  96. * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
  97. * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
  98. */
  99. export const EvpKDF = (password, salt, cfg) => EvpKDFAlgo.create(cfg).compute(password, salt);