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