/
gen.ts
61 lines (55 loc) · 1.92 KB
/
gen.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import type { LLEncrypt } from "@ndn/packet";
import { assert } from "@ndn/util";
/**
* Initialization Vector generator.
*
* @remarks
* The `.wrap()` method creates an {@link LLEncrypt.Key} or {@link LLEncrypt} that generates an
* IV for each message before encryption, and updates the internal state of this class after
* encryption. Typically, a separate IVGen instance should be used for each key.
*
* If a message presented for encryption already has an IV associated, it would bypass this class.
* In that case, the IV is not checked and the internal state is not updated.
*/
export abstract class IvGen {
constructor(public readonly ivLength: number) {
assert(ivLength > 0);
}
public wrap<T extends LLEncrypt.Key>(key: T): T;
public wrap(f: LLEncrypt): LLEncrypt;
public wrap(arg1: LLEncrypt | LLEncrypt.Key) {
if (typeof (arg1 as LLEncrypt.Key).llEncrypt === "function") {
return this.wrapKey(arg1 as LLEncrypt.Key);
}
return this.wrapLLEncrypt(arg1 as LLEncrypt);
}
private wrapKey(key: LLEncrypt.Key): any {
const f = this.wrapLLEncrypt((...args) => key.llEncrypt(...args));
return new Proxy(key, {
get(target, prop: keyof LLEncrypt.Key, receiver) {
if (prop === "llEncrypt") {
return f;
}
return Reflect.get(target, prop, receiver);
},
});
}
private wrapLLEncrypt(f: LLEncrypt): LLEncrypt {
return async (params) => {
if (params.iv) {
return f(params);
}
params.iv = this.generate();
const result = await f(params);
this.update(params.plaintext.length, result.ciphertext.length);
return result;
};
}
/** Generate IV for next message. */
protected abstract generate(): Uint8Array;
/** Update internal state after a message is encrypted.. */
protected update(plaintextLength: number, ciphertextLength: number): void {
void plaintextLength;
void ciphertextLength;
}
}