MCPcopy Create free account
hub / github.com/allocnode/oh-my-sage / AESGCMCipher

Class AESGCMCipher

ref/gateway_client.js:20–65  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

18
19// ==================== AES-GCM ====================
20class AESGCMCipher {
21 constructor(key, nonce) {
22 if (key.length !== 16) throw new Error('key must be 16 bytes');
23 if (nonce.length !== 8) throw new Error('nonce must be 8 bytes');
24 this.key = key;
25 this.nonce = nonce;
26 this.encryptCounter = 1;
27 this.decryptCounter = 0;
28 }
29
30 _makeIV(counter) {
31 const iv = Buffer.alloc(12);
32 this.nonce.copy(iv, 0);
33 iv.writeUInt32LE(counter, 8);
34 return iv;
35 }
36
37 encrypt(data) {
38 const counter = this.encryptCounter++;
39 const iv = this._makeIV(counter);
40 const cipher = crypto.createCipheriv('aes-128-gcm', this.key, iv);
41 const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
42 const tag = cipher.getAuthTag();
43
44 const result = Buffer.alloc(4 + encrypted.length + tag.length);
45 result.writeUInt32LE(counter, 0);
46 encrypted.copy(result, 4);
47 tag.copy(result, 4 + encrypted.length);
48 return result;
49 }
50
51 decrypt(data) {
52 if (data.length < 20) throw new Error('Data too short');
53 const counter = data.readUInt32LE(0);
54 if (counter <= this.decryptCounter) throw new Error('Replay attack');
55 this.decryptCounter = counter;
56
57 const ciphertext = data.slice(4, data.length - 16);
58 const tag = data.slice(data.length - 16);
59 const iv = this._makeIV(counter);
60
61 const decipher = crypto.createDecipheriv('aes-128-gcm', this.key, iv);
62 decipher.setAuthTag(tag);
63 return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
64 }
65}
66
67// ==================== 压缩/解压 ====================
68function compress(data) {

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected