dh.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { modPow, bigIntToU8Array, u8ArrayToBigInt } from "./bigint.js";
  2. class DHPublicKey {
  3. constructor(key) {
  4. this._key = key;
  5. }
  6. get algorithm() {
  7. return { name: "DH" };
  8. }
  9. exportKey() {
  10. return this._key;
  11. }
  12. }
  13. export class DHCipher {
  14. constructor() {
  15. this._g = null;
  16. this._p = null;
  17. this._gBigInt = null;
  18. this._pBigInt = null;
  19. this._privateKey = null;
  20. }
  21. get algorithm() {
  22. return { name: "DH" };
  23. }
  24. static generateKey(algorithm, _extractable) {
  25. const cipher = new DHCipher;
  26. cipher._generateKey(algorithm);
  27. return { privateKey: cipher, publicKey: new DHPublicKey(cipher._publicKey) };
  28. }
  29. _generateKey(algorithm) {
  30. const g = algorithm.g;
  31. const p = algorithm.p;
  32. this._keyBytes = p.length;
  33. this._gBigInt = u8ArrayToBigInt(g);
  34. this._pBigInt = u8ArrayToBigInt(p);
  35. this._privateKey = window.crypto.getRandomValues(new Uint8Array(this._keyBytes));
  36. this._privateKeyBigInt = u8ArrayToBigInt(this._privateKey);
  37. this._publicKey = bigIntToU8Array(modPow(
  38. this._gBigInt, this._privateKeyBigInt, this._pBigInt), this._keyBytes);
  39. }
  40. deriveBits(algorithm, length) {
  41. const bytes = Math.ceil(length / 8);
  42. const pkey = new Uint8Array(algorithm.public);
  43. const len = bytes > this._keyBytes ? bytes : this._keyBytes;
  44. const secret = modPow(u8ArrayToBigInt(pkey), this._privateKeyBigInt, this._pBigInt);
  45. return bigIntToU8Array(secret, len).slice(0, len);
  46. }
  47. }