pbkdf2.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /**
  2. * A **Password-Based Key-Derivation Function** is designed to create
  3. * a sequence of bytes suitible as a **key** from a human-rememberable
  4. * password.
  5. *
  6. * @_subsection: api/crypto:Passwords [about-pbkdf]
  7. */
  8. import { pbkdf2Sync } from "./crypto.js";
  9. import { getBytes, hexlify } from "../utils/index.js";
  10. import type { BytesLike } from "../utils/index.js";
  11. let locked = false;
  12. const _pbkdf2 = function(password: Uint8Array, salt: Uint8Array, iterations: number, keylen: number, algo: "sha256" | "sha512"): BytesLike {
  13. return pbkdf2Sync(password, salt, iterations, keylen, algo);
  14. }
  15. let __pbkdf2 = _pbkdf2;
  16. /**
  17. * Return the [[link-pbkdf2]] for %%keylen%% bytes for %%password%% using
  18. * the %%salt%% and using %%iterations%% of %%algo%%.
  19. *
  20. * This PBKDF is outdated and should not be used in new projects, but is
  21. * required to decrypt older files.
  22. *
  23. * @example:
  24. * // The password must be converted to bytes, and it is generally
  25. * // best practices to ensure the string has been normalized. Many
  26. * // formats explicitly indicate the normalization form to use.
  27. * password = "hello"
  28. * passwordBytes = toUtf8Bytes(password, "NFKC")
  29. *
  30. * salt = id("some-salt")
  31. *
  32. * // Compute the PBKDF2
  33. * pbkdf2(passwordBytes, salt, 1024, 16, "sha256")
  34. * //_result:
  35. */
  36. export function pbkdf2(_password: BytesLike, _salt: BytesLike, iterations: number, keylen: number, algo: "sha256" | "sha512"): string {
  37. const password = getBytes(_password, "password");
  38. const salt = getBytes(_salt, "salt");
  39. return hexlify(__pbkdf2(password, salt, iterations, keylen, algo));
  40. }
  41. pbkdf2._ = _pbkdf2;
  42. pbkdf2.lock = function(): void { locked = true; }
  43. pbkdf2.register = function(func: (password: Uint8Array, salt: Uint8Array, iterations: number, keylen: number, algo: "sha256" | "sha512") => BytesLike) {
  44. if (locked) { throw new Error("pbkdf2 is locked"); }
  45. __pbkdf2 = func;
  46. }
  47. Object.freeze(pbkdf2);