@thenewlabs/entangle-crypto 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +167 -0
- package/dist/index.test.js.map +1 -0
- package/dist/stream-crypto.d.ts +9 -0
- package/dist/stream-crypto.d.ts.map +1 -0
- package/dist/stream-crypto.js +38 -0
- package/dist/stream-crypto.js.map +1 -0
- package/package.json +26 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface DerivedKeys {
|
|
2
|
+
K_enc: Uint8Array;
|
|
3
|
+
K_auth: Uint8Array;
|
|
4
|
+
}
|
|
5
|
+
export declare function initCrypto(): Promise<void>;
|
|
6
|
+
export declare function extractSaltFromCapId(capId: string): Uint8Array;
|
|
7
|
+
export declare function generateCapId(): {
|
|
8
|
+
capId: string;
|
|
9
|
+
saltCap: Uint8Array;
|
|
10
|
+
};
|
|
11
|
+
export declare function generateSecret(): string;
|
|
12
|
+
export declare function deriveKeys(S: Uint8Array | string, saltCap: Uint8Array): Promise<DerivedKeys>;
|
|
13
|
+
export interface AeadEncResult {
|
|
14
|
+
nonce: Uint8Array;
|
|
15
|
+
cipher: Uint8Array;
|
|
16
|
+
}
|
|
17
|
+
export declare function aeadEncrypt(K_enc: Uint8Array, type: number, ctr: number, plaintext: any): AeadEncResult;
|
|
18
|
+
export declare function aeadDecrypt(K_enc: Uint8Array, type: number, nonce: Uint8Array, cipher: Uint8Array): {
|
|
19
|
+
ctr: number;
|
|
20
|
+
msg: any;
|
|
21
|
+
};
|
|
22
|
+
export declare function computeHmac(K_auth: Uint8Array, data: Uint8Array): Uint8Array;
|
|
23
|
+
export declare function verifyHmac(K_auth: Uint8Array, data: Uint8Array, mac: Uint8Array): boolean;
|
|
24
|
+
export declare function sha256Hex(text: string): string;
|
|
25
|
+
export declare function base64UrlEncode(data: Uint8Array): string;
|
|
26
|
+
export declare function base64UrlDecode(str: string): Uint8Array;
|
|
27
|
+
export declare function hashPolicy(policy: any): string;
|
|
28
|
+
export * from './stream-crypto.js';
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;CACpB;AAID,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAY9D;AAED,wBAAgB,aAAa,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,CAUtE;AAED,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CA0BlG;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,GAAG,GACb,aAAa,CAcf;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,UAAU,GACjB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,CAa3B;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAE5E;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAGzF;AAGD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAUxD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAcvD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,CAI9C;AAED,cAAc,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import sodium from 'libsodium-wrappers-sumo';
|
|
2
|
+
import { hkdf } from '@noble/hashes/hkdf';
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
4
|
+
import { hmac } from '@noble/hashes/hmac';
|
|
5
|
+
import { encode, decode } from 'cborg';
|
|
6
|
+
import { CRYPTO_PARAMS } from '@thenewlabs/entangle-protocol';
|
|
7
|
+
let sodiumReady = false;
|
|
8
|
+
export async function initCrypto() {
|
|
9
|
+
if (!sodiumReady) {
|
|
10
|
+
await sodium.ready;
|
|
11
|
+
sodiumReady = true;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function extractSaltFromCapId(capId) {
|
|
15
|
+
let decoded;
|
|
16
|
+
try {
|
|
17
|
+
decoded = base64UrlDecode(capId);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
throw new Error('Invalid capId length');
|
|
21
|
+
}
|
|
22
|
+
if (decoded.length !== CRYPTO_PARAMS.SALT_CAP_BYTES + CRYPTO_PARAMS.CAP_RAND_BYTES) {
|
|
23
|
+
throw new Error('Invalid capId length');
|
|
24
|
+
}
|
|
25
|
+
return decoded.slice(0, CRYPTO_PARAMS.SALT_CAP_BYTES);
|
|
26
|
+
}
|
|
27
|
+
export function generateCapId() {
|
|
28
|
+
const saltCap = sodium.randombytes_buf(CRYPTO_PARAMS.SALT_CAP_BYTES);
|
|
29
|
+
const capRand = sodium.randombytes_buf(CRYPTO_PARAMS.CAP_RAND_BYTES);
|
|
30
|
+
const combined = new Uint8Array(CRYPTO_PARAMS.SALT_CAP_BYTES + CRYPTO_PARAMS.CAP_RAND_BYTES);
|
|
31
|
+
combined.set(saltCap, 0);
|
|
32
|
+
combined.set(capRand, CRYPTO_PARAMS.SALT_CAP_BYTES);
|
|
33
|
+
return {
|
|
34
|
+
capId: base64UrlEncode(combined),
|
|
35
|
+
saltCap,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function generateSecret() {
|
|
39
|
+
const secret = sodium.randombytes_buf(32);
|
|
40
|
+
return base64UrlEncode(secret);
|
|
41
|
+
}
|
|
42
|
+
export async function deriveKeys(S, saltCap) {
|
|
43
|
+
await initCrypto();
|
|
44
|
+
const secretBytes = typeof S === 'string' ? base64UrlDecode(S) : S;
|
|
45
|
+
const K_raw = sodium.crypto_pwhash(32, secretBytes, saltCap, sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE, sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE, sodium.crypto_pwhash_ALG_ARGON2ID13);
|
|
46
|
+
const derived = hkdf(sha256, K_raw, new Uint8Array(0), new TextEncoder().encode('entangle-capability'), 64);
|
|
47
|
+
return {
|
|
48
|
+
K_enc: derived.slice(0, 32),
|
|
49
|
+
K_auth: derived.slice(32, 64),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export function aeadEncrypt(K_enc, type, ctr, plaintext) {
|
|
53
|
+
const nonce = sodium.randombytes_buf(CRYPTO_PARAMS.NONCE_BYTES);
|
|
54
|
+
const aad = encode({ type });
|
|
55
|
+
const pt = encode({ ctr, msg: plaintext });
|
|
56
|
+
const cipher = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(pt, aad, null, nonce, K_enc);
|
|
57
|
+
return { nonce, cipher };
|
|
58
|
+
}
|
|
59
|
+
export function aeadDecrypt(K_enc, type, nonce, cipher) {
|
|
60
|
+
const aad = encode({ type });
|
|
61
|
+
const pt = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(null, cipher, aad, nonce, K_enc);
|
|
62
|
+
const decoded = decode(pt);
|
|
63
|
+
return decoded;
|
|
64
|
+
}
|
|
65
|
+
export function computeHmac(K_auth, data) {
|
|
66
|
+
return hmac(sha256, K_auth, data);
|
|
67
|
+
}
|
|
68
|
+
export function verifyHmac(K_auth, data, mac) {
|
|
69
|
+
const computed = computeHmac(K_auth, data);
|
|
70
|
+
return sodium.compare(computed, mac) === 0;
|
|
71
|
+
}
|
|
72
|
+
// Convenience: SHA-256 of UTF-8 string, returned as lowercase hex
|
|
73
|
+
export function sha256Hex(text) {
|
|
74
|
+
const bytes = new TextEncoder().encode(text);
|
|
75
|
+
const hash = sha256(bytes);
|
|
76
|
+
let hex = '';
|
|
77
|
+
// Iterate without indexed access to satisfy noUncheckedIndexedAccess
|
|
78
|
+
for (const b of hash)
|
|
79
|
+
hex += b.toString(16).padStart(2, '0');
|
|
80
|
+
return hex;
|
|
81
|
+
}
|
|
82
|
+
export function base64UrlEncode(data) {
|
|
83
|
+
// Use Node Buffer when available to avoid relying on btoa (not in Node)
|
|
84
|
+
let base64;
|
|
85
|
+
if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {
|
|
86
|
+
base64 = Buffer.from(data).toString('base64');
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Browser fallback
|
|
90
|
+
base64 = btoa(String.fromCharCode(...data));
|
|
91
|
+
}
|
|
92
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
|
|
93
|
+
}
|
|
94
|
+
export function base64UrlDecode(str) {
|
|
95
|
+
let base64 = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
96
|
+
while (base64.length % 4) {
|
|
97
|
+
base64 += '=';
|
|
98
|
+
}
|
|
99
|
+
if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {
|
|
100
|
+
return new Uint8Array(Buffer.from(base64, 'base64'));
|
|
101
|
+
}
|
|
102
|
+
const binary = atob(base64);
|
|
103
|
+
const bytes = new Uint8Array(binary.length);
|
|
104
|
+
for (let i = 0; i < binary.length; i++) {
|
|
105
|
+
bytes[i] = binary.charCodeAt(i);
|
|
106
|
+
}
|
|
107
|
+
return bytes;
|
|
108
|
+
}
|
|
109
|
+
export function hashPolicy(policy) {
|
|
110
|
+
const encoded = encode(policy);
|
|
111
|
+
const hash = sha256(encoded);
|
|
112
|
+
return base64UrlEncode(hash);
|
|
113
|
+
}
|
|
114
|
+
export * from './stream-crypto.js';
|
|
115
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
+
import { initCrypto, generateCapId, generateSecret, extractSaltFromCapId, deriveKeys, aeadEncrypt, aeadDecrypt, computeHmac, verifyHmac, base64UrlEncode, base64UrlDecode, hashPolicy, } from './index.js';
|
|
3
|
+
describe('Crypto Package', () => {
|
|
4
|
+
beforeAll(async () => {
|
|
5
|
+
await initCrypto();
|
|
6
|
+
});
|
|
7
|
+
describe('CapId generation', () => {
|
|
8
|
+
it('should generate valid capId with embedded salt', () => {
|
|
9
|
+
const { capId, saltCap } = generateCapId();
|
|
10
|
+
expect(capId).toBeTruthy();
|
|
11
|
+
expect(saltCap).toHaveLength(16);
|
|
12
|
+
const extracted = extractSaltFromCapId(capId);
|
|
13
|
+
expect(extracted).toEqual(saltCap);
|
|
14
|
+
});
|
|
15
|
+
it('should generate unique capIds', () => {
|
|
16
|
+
const cap1 = generateCapId();
|
|
17
|
+
const cap2 = generateCapId();
|
|
18
|
+
expect(cap1.capId).not.toEqual(cap2.capId);
|
|
19
|
+
expect(cap1.saltCap).not.toEqual(cap2.saltCap);
|
|
20
|
+
});
|
|
21
|
+
it('should fail on invalid capId length', () => {
|
|
22
|
+
expect(() => extractSaltFromCapId('short')).toThrow('Invalid capId length');
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe('Secret generation', () => {
|
|
26
|
+
it('should generate base64url encoded secrets', () => {
|
|
27
|
+
const secret = generateSecret();
|
|
28
|
+
expect(secret).toBeTruthy();
|
|
29
|
+
expect(secret).toMatch(/^[A-Za-z0-9_-]+$/);
|
|
30
|
+
const decoded = base64UrlDecode(secret);
|
|
31
|
+
expect(decoded).toHaveLength(32);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('Key derivation', () => {
|
|
35
|
+
it('should derive consistent keys from same inputs', async () => {
|
|
36
|
+
const secret = generateSecret();
|
|
37
|
+
const { saltCap } = generateCapId();
|
|
38
|
+
const keys1 = await deriveKeys(secret, saltCap);
|
|
39
|
+
const keys2 = await deriveKeys(secret, saltCap);
|
|
40
|
+
expect(keys1.K_enc).toEqual(keys2.K_enc);
|
|
41
|
+
expect(keys1.K_auth).toEqual(keys2.K_auth);
|
|
42
|
+
});
|
|
43
|
+
it('should derive different keys from different secrets', async () => {
|
|
44
|
+
const secret1 = generateSecret();
|
|
45
|
+
const secret2 = generateSecret();
|
|
46
|
+
const { saltCap } = generateCapId();
|
|
47
|
+
const keys1 = await deriveKeys(secret1, saltCap);
|
|
48
|
+
const keys2 = await deriveKeys(secret2, saltCap);
|
|
49
|
+
expect(keys1.K_enc).not.toEqual(keys2.K_enc);
|
|
50
|
+
expect(keys1.K_auth).not.toEqual(keys2.K_auth);
|
|
51
|
+
});
|
|
52
|
+
it('should derive different keys from different salts', async () => {
|
|
53
|
+
const secret = generateSecret();
|
|
54
|
+
const { saltCap: salt1 } = generateCapId();
|
|
55
|
+
const { saltCap: salt2 } = generateCapId();
|
|
56
|
+
const keys1 = await deriveKeys(secret, salt1);
|
|
57
|
+
const keys2 = await deriveKeys(secret, salt2);
|
|
58
|
+
expect(keys1.K_enc).not.toEqual(keys2.K_enc);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('AEAD encryption', () => {
|
|
62
|
+
it('should encrypt and decrypt successfully', async () => {
|
|
63
|
+
const secret = generateSecret();
|
|
64
|
+
const { saltCap } = generateCapId();
|
|
65
|
+
const keys = await deriveKeys(secret, saltCap);
|
|
66
|
+
const plaintext = { test: 'data', number: 42 };
|
|
67
|
+
const type = 0x10;
|
|
68
|
+
const ctr = 1;
|
|
69
|
+
const { nonce, cipher } = aeadEncrypt(keys.K_enc, type, ctr, plaintext);
|
|
70
|
+
expect(nonce).toHaveLength(24);
|
|
71
|
+
expect(cipher).toBeTruthy();
|
|
72
|
+
const decrypted = aeadDecrypt(keys.K_enc, type, nonce, cipher);
|
|
73
|
+
expect(decrypted.ctr).toEqual(ctr);
|
|
74
|
+
expect(decrypted.msg).toEqual(plaintext);
|
|
75
|
+
});
|
|
76
|
+
it('should fail decryption with wrong key', async () => {
|
|
77
|
+
const secret1 = generateSecret();
|
|
78
|
+
const secret2 = generateSecret();
|
|
79
|
+
const { saltCap } = generateCapId();
|
|
80
|
+
const keys1 = await deriveKeys(secret1, saltCap);
|
|
81
|
+
const keys2 = await deriveKeys(secret2, saltCap);
|
|
82
|
+
const plaintext = { test: 'data' };
|
|
83
|
+
const { nonce, cipher } = aeadEncrypt(keys1.K_enc, 0x10, 1, plaintext);
|
|
84
|
+
expect(() => aeadDecrypt(keys2.K_enc, 0x10, nonce, cipher)).toThrow();
|
|
85
|
+
});
|
|
86
|
+
it('should fail decryption with wrong type', async () => {
|
|
87
|
+
const secret = generateSecret();
|
|
88
|
+
const { saltCap } = generateCapId();
|
|
89
|
+
const keys = await deriveKeys(secret, saltCap);
|
|
90
|
+
const plaintext = { test: 'data' };
|
|
91
|
+
const { nonce, cipher } = aeadEncrypt(keys.K_enc, 0x10, 1, plaintext);
|
|
92
|
+
expect(() => aeadDecrypt(keys.K_enc, 0x11, nonce, cipher)).toThrow();
|
|
93
|
+
});
|
|
94
|
+
it('should fail decryption with tampered cipher', async () => {
|
|
95
|
+
const secret = generateSecret();
|
|
96
|
+
const { saltCap } = generateCapId();
|
|
97
|
+
const keys = await deriveKeys(secret, saltCap);
|
|
98
|
+
const plaintext = { test: 'data' };
|
|
99
|
+
const { nonce, cipher } = aeadEncrypt(keys.K_enc, 0x10, 1, plaintext);
|
|
100
|
+
cipher[0] ^= 0xFF; // Tamper with first byte
|
|
101
|
+
expect(() => aeadDecrypt(keys.K_enc, 0x10, nonce, cipher)).toThrow();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
describe('HMAC', () => {
|
|
105
|
+
it('should compute and verify HMAC', async () => {
|
|
106
|
+
const secret = generateSecret();
|
|
107
|
+
const { saltCap } = generateCapId();
|
|
108
|
+
const keys = await deriveKeys(secret, saltCap);
|
|
109
|
+
const data = new TextEncoder().encode('test message');
|
|
110
|
+
const mac = computeHmac(keys.K_auth, data);
|
|
111
|
+
expect(mac).toHaveLength(32);
|
|
112
|
+
expect(verifyHmac(keys.K_auth, data, mac)).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
it('should fail verification with wrong key', async () => {
|
|
115
|
+
const secret1 = generateSecret();
|
|
116
|
+
const secret2 = generateSecret();
|
|
117
|
+
const { saltCap } = generateCapId();
|
|
118
|
+
const keys1 = await deriveKeys(secret1, saltCap);
|
|
119
|
+
const keys2 = await deriveKeys(secret2, saltCap);
|
|
120
|
+
const data = new TextEncoder().encode('test message');
|
|
121
|
+
const mac = computeHmac(keys1.K_auth, data);
|
|
122
|
+
expect(verifyHmac(keys2.K_auth, data, mac)).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
it('should fail verification with tampered data', async () => {
|
|
125
|
+
const secret = generateSecret();
|
|
126
|
+
const { saltCap } = generateCapId();
|
|
127
|
+
const keys = await deriveKeys(secret, saltCap);
|
|
128
|
+
const data1 = new TextEncoder().encode('test message');
|
|
129
|
+
const data2 = new TextEncoder().encode('test message!');
|
|
130
|
+
const mac = computeHmac(keys.K_auth, data1);
|
|
131
|
+
expect(verifyHmac(keys.K_auth, data2, mac)).toBe(false);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe('Base64URL encoding', () => {
|
|
135
|
+
it('should encode and decode correctly', () => {
|
|
136
|
+
const data = new Uint8Array([1, 2, 3, 255, 0, 128]);
|
|
137
|
+
const encoded = base64UrlEncode(data);
|
|
138
|
+
expect(encoded).not.toContain('+');
|
|
139
|
+
expect(encoded).not.toContain('/');
|
|
140
|
+
expect(encoded).not.toContain('=');
|
|
141
|
+
const decoded = base64UrlDecode(encoded);
|
|
142
|
+
expect(decoded).toEqual(data);
|
|
143
|
+
});
|
|
144
|
+
it('should handle empty data', () => {
|
|
145
|
+
const data = new Uint8Array(0);
|
|
146
|
+
const encoded = base64UrlEncode(data);
|
|
147
|
+
const decoded = base64UrlDecode(encoded);
|
|
148
|
+
expect(decoded).toEqual(data);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe('Policy hashing', () => {
|
|
152
|
+
it('should hash policy consistently', () => {
|
|
153
|
+
const policy = { singleRun: true };
|
|
154
|
+
const hash1 = hashPolicy(policy);
|
|
155
|
+
const hash2 = hashPolicy(policy);
|
|
156
|
+
expect(hash1).toEqual(hash2);
|
|
157
|
+
});
|
|
158
|
+
it('should produce different hashes for different policies', () => {
|
|
159
|
+
const policy1 = { singleRun: true };
|
|
160
|
+
const policy2 = { singleRun: false };
|
|
161
|
+
const hash1 = hashPolicy(policy1);
|
|
162
|
+
const hash2 = hashPolicy(policy2);
|
|
163
|
+
expect(hash1).not.toEqual(hash2);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,eAAe,EACf,eAAe,EACf,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,UAAU,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YAE3C,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;YAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAEjC,MAAM,SAAS,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;YAE7B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;YAEhC,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;YAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;YAE3C,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;YACxC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;YAChC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YAEpC,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAEhD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;YACjC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YAEpC,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAEjD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;YAChC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,aAAa,EAAE,CAAC;YAC3C,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,aAAa,EAAE,CAAC;YAE3C,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9C,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAE9C,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;YAChC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE/C,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAC/C,MAAM,IAAI,GAAG,IAAI,CAAC;YAClB,MAAM,GAAG,GAAG,CAAC,CAAC;YAEd,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;YAExE,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;YAE5B,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YAE/D,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACrD,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;YACjC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YAEpC,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAEjD,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACnC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YAEvE,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;YAChC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE/C,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACnC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YAEtE,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;YAChC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE/C,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACnC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YAEtE,MAAM,CAAC,CAAC,CAAE,IAAI,IAAI,CAAC,CAAC,yBAAyB;YAE7C,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;YAChC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE/C,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACtD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAE3C,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC7B,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;YACjC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YAEpC,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAEjD,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACtD,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAE5C,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;YAChC,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE/C,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACvD,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YACxD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAE5C,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YAEtC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAEnC,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YACzC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAEzC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,MAAM,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;YAEnC,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;YAEjC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,OAAO,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;YACpC,MAAM,OAAO,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YAErC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;YAElC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream-aware AEAD encryption that handles counters separately
|
|
3
|
+
*/
|
|
4
|
+
export declare function streamAeadEncrypt(K_enc: Uint8Array, plaintext: Uint8Array, aad: Uint8Array): Promise<Uint8Array>;
|
|
5
|
+
/**
|
|
6
|
+
* Stream-aware AEAD decryption that handles counters separately
|
|
7
|
+
*/
|
|
8
|
+
export declare function streamAeadDecrypt(K_enc: Uint8Array, payload: Uint8Array, aad: Uint8Array): Promise<Uint8Array>;
|
|
9
|
+
//# sourceMappingURL=stream-crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-crypto.d.ts","sourceRoot":"","sources":["../src/stream-crypto.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,UAAU,CAAC,CAmBrB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,UAAU,EACnB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,UAAU,CAAC,CA2BrB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import sodium from 'libsodium-wrappers-sumo';
|
|
2
|
+
import { CRYPTO_PARAMS } from '@thenewlabs/entangle-protocol';
|
|
3
|
+
/**
|
|
4
|
+
* Stream-aware AEAD encryption that handles counters separately
|
|
5
|
+
*/
|
|
6
|
+
export async function streamAeadEncrypt(K_enc, plaintext, aad) {
|
|
7
|
+
await sodium.ready;
|
|
8
|
+
const nonce = sodium.randombytes_buf(CRYPTO_PARAMS.NONCE_BYTES);
|
|
9
|
+
const cipher = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, aad, null, nonce, K_enc);
|
|
10
|
+
// Combine nonce and cipher for transport
|
|
11
|
+
const result = new Uint8Array(nonce.length + cipher.length);
|
|
12
|
+
result.set(nonce, 0);
|
|
13
|
+
result.set(cipher, nonce.length);
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Stream-aware AEAD decryption that handles counters separately
|
|
18
|
+
*/
|
|
19
|
+
export async function streamAeadDecrypt(K_enc, payload, aad) {
|
|
20
|
+
await sodium.ready;
|
|
21
|
+
const minLength = CRYPTO_PARAMS.NONCE_BYTES + sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES;
|
|
22
|
+
if (payload.length < minLength) {
|
|
23
|
+
throw new Error(`Payload too short: expected at least ${minLength} bytes, got ${payload.length}`);
|
|
24
|
+
}
|
|
25
|
+
const nonce = payload.slice(0, CRYPTO_PARAMS.NONCE_BYTES);
|
|
26
|
+
const cipher = payload.slice(CRYPTO_PARAMS.NONCE_BYTES);
|
|
27
|
+
try {
|
|
28
|
+
// NOTE: libsodium-wrappers signature is (nsec, cipher, aad, nonce, key)
|
|
29
|
+
// Keep it consistent with aeadDecrypt in index.ts
|
|
30
|
+
const plaintext = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(null, cipher, aad, nonce, K_enc);
|
|
31
|
+
return plaintext;
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
// Add more context to the error
|
|
35
|
+
throw new Error(`streamAeadDecrypt failed: ${e.message || e}. Payload length: ${payload.length}, Nonce length: ${nonce.length}, Cipher length: ${cipher.length}, Key length: ${K_enc.length}, AAD length: ${aad.length}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=stream-crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-crypto.js","sourceRoot":"","sources":["../src/stream-crypto.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAiB,EACjB,SAAqB,EACrB,GAAe;IAEf,MAAM,MAAM,CAAC,KAAK,CAAC;IAEnB,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,MAAM,CAAC,0CAA0C,CAC9D,SAAS,EACT,GAAG,EACH,IAAI,EACJ,KAAK,EACL,KAAK,CACN,CAAC;IAEF,yCAAyC;IACzC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAEjC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAiB,EACjB,OAAmB,EACnB,GAAe;IAEf,MAAM,MAAM,CAAC,KAAK,CAAC;IAEnB,MAAM,SAAS,GAAG,aAAa,CAAC,WAAW,GAAG,MAAM,CAAC,yCAAyC,CAAC;IAC/F,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,wCAAwC,SAAS,eAAe,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpG,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAExD,IAAI,CAAC;QACH,wEAAwE;QACxE,kDAAkD;QAClD,MAAM,SAAS,GAAG,MAAM,CAAC,0CAA0C,CACjE,IAAI,EACJ,MAAM,EACN,GAAG,EACH,KAAK,EACL,KAAK,CACN,CAAC;QAEF,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,gCAAgC;QAChC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,OAAO,IAAI,CAAC,qBAAqB,OAAO,CAAC,MAAM,mBAAmB,KAAK,CAAC,MAAM,oBAAoB,MAAM,CAAC,MAAM,iBAAiB,KAAK,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5N,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thenewlabs/entangle-crypto",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"clean": "rm -rf dist",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@noble/hashes": "^1.8.0",
|
|
14
|
+
"@thenewlabs/entangle-protocol": "^1.0.0",
|
|
15
|
+
"cborg": "^4.5.8",
|
|
16
|
+
"libsodium-wrappers-sumo": "^0.8.4"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/libsodium-wrappers-sumo": "^0.8.2",
|
|
20
|
+
"@types/node": "^20.19.43",
|
|
21
|
+
"typescript": "^5.9.3"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
]
|
|
26
|
+
}
|