@agentdock/crypto 0.0.1

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.
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Base64 and Base64URL encoding/decoding utilities.
3
+ *
4
+ * Uses browser-compatible APIs (no Node.js Buffer dependency).
5
+ * Works in both browser and Node.js 22+ environments.
6
+ */
7
+ /**
8
+ * Encode a Uint8Array to a standard Base64 string.
9
+ */
10
+ export function encodeBase64(buffer) {
11
+ if (buffer.length === 0)
12
+ return '';
13
+ // Convert Uint8Array to binary string, then use btoa
14
+ let binary = '';
15
+ for (let i = 0; i < buffer.length; i++) {
16
+ binary += String.fromCharCode(buffer[i]);
17
+ }
18
+ return btoa(binary);
19
+ }
20
+ /**
21
+ * Decode a standard Base64 string to a Uint8Array.
22
+ */
23
+ export function decodeBase64(base64) {
24
+ if (base64 === '')
25
+ return new Uint8Array(0);
26
+ const binary = atob(base64);
27
+ const bytes = new Uint8Array(binary.length);
28
+ for (let i = 0; i < binary.length; i++) {
29
+ bytes[i] = binary.charCodeAt(i);
30
+ }
31
+ return bytes;
32
+ }
33
+ /**
34
+ * Encode a Uint8Array to a Base64URL string (no padding).
35
+ *
36
+ * Base64URL replaces `+` with `-`, `/` with `_`, and strips `=` padding.
37
+ */
38
+ export function encodeBase64Url(buffer) {
39
+ const base64 = encodeBase64(buffer);
40
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
41
+ }
42
+ /**
43
+ * Decode a Base64URL string to a Uint8Array.
44
+ */
45
+ export function decodeBase64Url(base64url) {
46
+ if (base64url === '')
47
+ return new Uint8Array(0);
48
+ // Convert base64url back to standard base64
49
+ let base64 = base64url.replace(/-/g, '+').replace(/_/g, '/');
50
+ // Restore padding
51
+ const paddingNeeded = (4 - (base64.length % 4)) % 4;
52
+ base64 += '='.repeat(paddingNeeded);
53
+ return decodeBase64(base64);
54
+ }
55
+ //# sourceMappingURL=encoding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,qDAAqD;IACrD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAW,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAkB;IAChD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAE/C,4CAA4C;IAC5C,IAAI,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC7D,kBAAkB;IAClB,MAAM,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAEpC,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC"}
package/dist/hmac.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Compute HMAC-SHA512 of data using the given key.
3
+ *
4
+ * Uses Web Crypto API (globalThis.crypto.subtle) for cross-platform
5
+ * compatibility between browsers and Node.js 22+.
6
+ *
7
+ * @param key - HMAC key (must be at least 1 byte; will be hashed if > block size)
8
+ * @param data - Data to authenticate
9
+ * @returns 64-byte HMAC-SHA512 digest
10
+ * @throws Error if key is empty (zero-length keys are not supported by Web Crypto API)
11
+ */
12
+ export declare function hmacSha512(key: Uint8Array, data: Uint8Array): Promise<Uint8Array>;
13
+ //# sourceMappingURL=hmac.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmac.d.ts","sourceRoot":"","sources":["../src/hmac.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAcvF"}
package/dist/hmac.js ADDED
@@ -0,0 +1,25 @@
1
+ // @agentdock/crypto — HMAC-SHA512 using Web Crypto API
2
+ // Browser + Node.js 22+ compatible (no node:crypto)
3
+ /**
4
+ * Compute HMAC-SHA512 of data using the given key.
5
+ *
6
+ * Uses Web Crypto API (globalThis.crypto.subtle) for cross-platform
7
+ * compatibility between browsers and Node.js 22+.
8
+ *
9
+ * @param key - HMAC key (must be at least 1 byte; will be hashed if > block size)
10
+ * @param data - Data to authenticate
11
+ * @returns 64-byte HMAC-SHA512 digest
12
+ * @throws Error if key is empty (zero-length keys are not supported by Web Crypto API)
13
+ */
14
+ export async function hmacSha512(key, data) {
15
+ if (key.byteLength === 0) {
16
+ throw new Error('HMAC key must not be empty');
17
+ }
18
+ const algorithm = { name: 'HMAC', hash: 'SHA-512' };
19
+ const cryptoKey = await crypto.subtle.importKey('raw', key, algorithm, false, [
20
+ 'sign',
21
+ ]);
22
+ const signature = await crypto.subtle.sign('HMAC', cryptoKey, data);
23
+ return new Uint8Array(signature);
24
+ }
25
+ //# sourceMappingURL=hmac.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmac.js","sourceRoot":"","sources":["../src/hmac.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,oDAAoD;AAEpD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAe,EAAE,IAAgB;IAChE,IAAI,GAAG,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAW,CAAC;IAE7D,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAmB,EAAE,SAAS,EAAE,KAAK,EAAE;QAC5F,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAoB,CAAC,CAAC;IAEpF,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,14 @@
1
+ export { encodeBase64, decodeBase64, encodeBase64Url, decodeBase64Url } from './encoding.js';
2
+ export { getRandomBytes } from './random.js';
3
+ export { encryptAesGcm, decryptAesGcm } from './aes.js';
4
+ export { hmacSha512 } from './hmac.js';
5
+ export { deriveSecretKeyTreeRoot, deriveSecretKeyTreeChild, deriveKey } from './keys.js';
6
+ export type { KeyTreeState } from './keys.js';
7
+ export { authChallenge, signChallenge, verifyChallenge } from './auth.js';
8
+ export type { AuthChallengeResult } from './auth.js';
9
+ export { encryptBox, decryptBox, boxPublicKeyFromSecretKey, generateBoxKeyPair } from './box.js';
10
+ export type { BoxKeyPair } from './box.js';
11
+ export { encryptSecretBox, decryptSecretBox } from './secretbox.js';
12
+ export { deriveContentKeyPair } from './content.js';
13
+ export { generateSessionKeys, unwrapSessionKey, encryptEnvelope, decryptEnvelope, } from './session.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAG7F,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvC,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACzF,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC1E,YAAY,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACjG,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAG3C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGpD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ // @agentdock/crypto — E2E encryption for AgentDock
2
+ // Web Crypto API + tweetnacl, browser + Node.js 22+ compatible
3
+ // Base64 encoding/decoding
4
+ export { encodeBase64, decodeBase64, encodeBase64Url, decodeBase64Url } from './encoding.js';
5
+ // Secure random number generation
6
+ export { getRandomBytes } from './random.js';
7
+ // AES-256-GCM encryption/decryption
8
+ export { encryptAesGcm, decryptAesGcm } from './aes.js';
9
+ // HMAC-SHA512
10
+ export { hmacSha512 } from './hmac.js';
11
+ // Key derivation tree
12
+ export { deriveSecretKeyTreeRoot, deriveSecretKeyTreeChild, deriveKey } from './keys.js';
13
+ // Authentication challenge (Ed25519)
14
+ export { authChallenge, signChallenge, verifyChallenge } from './auth.js';
15
+ // NaCl Box encryption (public key / key delivery)
16
+ export { encryptBox, decryptBox, boxPublicKeyFromSecretKey, generateBoxKeyPair } from './box.js';
17
+ // NaCl SecretBox encryption (symmetric / legacy)
18
+ export { encryptSecretBox, decryptSecretBox } from './secretbox.js';
19
+ // Content keypair derivation
20
+ export { deriveContentKeyPair } from './content.js';
21
+ // Session encryption (high-level API)
22
+ export { generateSessionKeys, unwrapSessionKey, encryptEnvelope, decryptEnvelope, } from './session.js';
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,+DAA+D;AAE/D,2BAA2B;AAC3B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE7F,kCAAkC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,oCAAoC;AACpC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAExD,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,sBAAsB;AACtB,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGzF,qCAAqC;AACrC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAG1E,kDAAkD;AAClD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAGjG,iDAAiD;AACjD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEpE,6BAA6B;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,sCAAsC;AACtC,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,cAAc,CAAC"}
package/dist/keys.d.ts ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Immutable state of a node in the key derivation tree.
3
+ * Splitting the HMAC-SHA512 output (64 bytes) into:
4
+ * - key (first 32 bytes): the derived secret key
5
+ * - chainCode (last 32 bytes): used to derive child keys
6
+ */
7
+ export type KeyTreeState = {
8
+ readonly key: Uint8Array;
9
+ readonly chainCode: Uint8Array;
10
+ };
11
+ /**
12
+ * Derive the root key tree state from a seed and usage string.
13
+ *
14
+ * Formula: HMAC-SHA512(encode(usage + " Master Seed"), seed)
15
+ * - The HMAC key is the UTF-8 encoding of `usage + " Master Seed"`
16
+ * - The HMAC data is the raw seed bytes
17
+ *
18
+ * @param seed - Root seed material
19
+ * @param usage - Purpose string (e.g., "encryption", "authentication")
20
+ * @returns Root KeyTreeState with key and chainCode
21
+ */
22
+ export declare function deriveSecretKeyTreeRoot(seed: Uint8Array, usage: string): Promise<KeyTreeState>;
23
+ /**
24
+ * Derive a child key tree state from a parent chain code and index.
25
+ *
26
+ * Formula: HMAC-SHA512(parentChainCode, [0x00, ...encode(index)])
27
+ * - Prepends a 0x00 byte before the index string encoding
28
+ *
29
+ * @param chainCode - Parent node's chain code (32 bytes)
30
+ * @param index - Child index identifier string
31
+ * @returns Child KeyTreeState with key and chainCode
32
+ */
33
+ export declare function deriveSecretKeyTreeChild(chainCode: Uint8Array, index: string): Promise<KeyTreeState>;
34
+ /**
35
+ * Convenience function: derive a final key by walking a path from root.
36
+ *
37
+ * 1. Derive root from master seed + usage
38
+ * 2. For each segment in path, derive child from current chainCode
39
+ * 3. Return the final key (32 bytes)
40
+ *
41
+ * @param master - Master seed material
42
+ * @param usage - Purpose string for root derivation
43
+ * @param path - Array of path segments to walk
44
+ * @returns Final derived key (32 bytes)
45
+ */
46
+ export declare function deriveKey(master: Uint8Array, usage: string, path: readonly string[]): Promise<Uint8Array>;
47
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;CAChC,CAAC;AAcF;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAIvB;AAED;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAQvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,OAAO,CAAC,UAAU,CAAC,CAQrB"}
package/dist/keys.js ADDED
@@ -0,0 +1,67 @@
1
+ // @agentdock/crypto — HMAC-SHA512 key derivation tree
2
+ // Compatible with Happy project's key tree pattern, using Web Crypto API
3
+ import { hmacSha512 } from './hmac.js';
4
+ const encoder = new TextEncoder();
5
+ /**
6
+ * Split a 64-byte HMAC output into key (first 32) and chainCode (last 32).
7
+ */
8
+ function splitHmacOutput(hmacOutput) {
9
+ return {
10
+ key: hmacOutput.slice(0, 32),
11
+ chainCode: hmacOutput.slice(32, 64),
12
+ };
13
+ }
14
+ /**
15
+ * Derive the root key tree state from a seed and usage string.
16
+ *
17
+ * Formula: HMAC-SHA512(encode(usage + " Master Seed"), seed)
18
+ * - The HMAC key is the UTF-8 encoding of `usage + " Master Seed"`
19
+ * - The HMAC data is the raw seed bytes
20
+ *
21
+ * @param seed - Root seed material
22
+ * @param usage - Purpose string (e.g., "encryption", "authentication")
23
+ * @returns Root KeyTreeState with key and chainCode
24
+ */
25
+ export async function deriveSecretKeyTreeRoot(seed, usage) {
26
+ const hmacKey = encoder.encode(usage + ' Master Seed');
27
+ const hmacOutput = await hmacSha512(hmacKey, seed);
28
+ return splitHmacOutput(hmacOutput);
29
+ }
30
+ /**
31
+ * Derive a child key tree state from a parent chain code and index.
32
+ *
33
+ * Formula: HMAC-SHA512(parentChainCode, [0x00, ...encode(index)])
34
+ * - Prepends a 0x00 byte before the index string encoding
35
+ *
36
+ * @param chainCode - Parent node's chain code (32 bytes)
37
+ * @param index - Child index identifier string
38
+ * @returns Child KeyTreeState with key and chainCode
39
+ */
40
+ export async function deriveSecretKeyTreeChild(chainCode, index) {
41
+ const indexBytes = encoder.encode(index);
42
+ const data = new Uint8Array(1 + indexBytes.byteLength);
43
+ data[0] = 0x00;
44
+ data.set(indexBytes, 1);
45
+ const hmacOutput = await hmacSha512(chainCode, data);
46
+ return splitHmacOutput(hmacOutput);
47
+ }
48
+ /**
49
+ * Convenience function: derive a final key by walking a path from root.
50
+ *
51
+ * 1. Derive root from master seed + usage
52
+ * 2. For each segment in path, derive child from current chainCode
53
+ * 3. Return the final key (32 bytes)
54
+ *
55
+ * @param master - Master seed material
56
+ * @param usage - Purpose string for root derivation
57
+ * @param path - Array of path segments to walk
58
+ * @returns Final derived key (32 bytes)
59
+ */
60
+ export async function deriveKey(master, usage, path) {
61
+ let state = await deriveSecretKeyTreeRoot(master, usage);
62
+ for (const segment of path) {
63
+ state = await deriveSecretKeyTreeChild(state.chainCode, segment);
64
+ }
65
+ return state.key;
66
+ }
67
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,yEAAyE;AAEzE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAavC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC;;GAEG;AACH,SAAS,eAAe,CAAC,UAAsB;IAC7C,OAAO;QACL,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5B,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;KACpC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,IAAgB,EAChB,KAAa;IAEb,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,cAAc,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACnD,OAAO,eAAe,CAAC,UAAU,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,SAAqB,EACrB,KAAa;IAEb,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACvD,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACf,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAExB,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACrD,OAAO,eAAe,CAAC,UAAU,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAkB,EAClB,KAAa,EACb,IAAuB;IAEvB,IAAI,KAAK,GAAG,MAAM,uBAAuB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAEzD,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;QAC3B,KAAK,GAAG,MAAM,wBAAwB,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC;AACnB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Cryptographically secure random number generation.
3
+ *
4
+ * Uses the Web Crypto API (globalThis.crypto.getRandomValues),
5
+ * compatible with both browsers and Node.js 22+.
6
+ */
7
+ /**
8
+ * Generate cryptographically secure random bytes.
9
+ *
10
+ * @param size - Number of random bytes to generate (0 or more).
11
+ * @returns A new Uint8Array filled with random bytes.
12
+ */
13
+ export declare function getRandomBytes(size: number): Uint8Array;
14
+ //# sourceMappingURL=random.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAMvD"}
package/dist/random.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Cryptographically secure random number generation.
3
+ *
4
+ * Uses the Web Crypto API (globalThis.crypto.getRandomValues),
5
+ * compatible with both browsers and Node.js 22+.
6
+ */
7
+ /**
8
+ * Generate cryptographically secure random bytes.
9
+ *
10
+ * @param size - Number of random bytes to generate (0 or more).
11
+ * @returns A new Uint8Array filled with random bytes.
12
+ */
13
+ export function getRandomBytes(size) {
14
+ const buffer = new Uint8Array(size);
15
+ if (size > 0) {
16
+ globalThis.crypto.getRandomValues(buffer);
17
+ }
18
+ return buffer;
19
+ }
20
+ //# sourceMappingURL=random.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.js","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * NaCl SecretBox encryption — aligned with Happy.
3
+ *
4
+ * Symmetric authenticated encryption (XSalsa20-Poly1305).
5
+ * Used for legacy encryption mode.
6
+ *
7
+ * Bundle format: nonce(24) + ciphertext
8
+ */
9
+ /**
10
+ * Encrypt data with a secret key using NaCl SecretBox.
11
+ *
12
+ * JSON-serializes the data, then encrypts with XSalsa20-Poly1305.
13
+ *
14
+ * @param data - Data to encrypt (will be JSON-serialized)
15
+ * @param secret - 32-byte secret key
16
+ * @returns Bundle: nonce(24) + ciphertext
17
+ */
18
+ export declare function encryptSecretBox(data: unknown, secret: Uint8Array): Uint8Array;
19
+ /**
20
+ * Decrypt a NaCl SecretBox bundle with a secret key.
21
+ *
22
+ * @param bundle - Bundle: nonce(24) + ciphertext
23
+ * @param secret - 32-byte secret key
24
+ * @returns Deserialized data, or null if decryption fails
25
+ */
26
+ export declare function decryptSecretBox(bundle: Uint8Array, secret: Uint8Array): unknown | null;
27
+ //# sourceMappingURL=secretbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretbox.d.ts","sourceRoot":"","sources":["../src/secretbox.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAS9E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,IAAI,CAcvF"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * NaCl SecretBox encryption — aligned with Happy.
3
+ *
4
+ * Symmetric authenticated encryption (XSalsa20-Poly1305).
5
+ * Used for legacy encryption mode.
6
+ *
7
+ * Bundle format: nonce(24) + ciphertext
8
+ */
9
+ import nacl from 'tweetnacl';
10
+ import { getRandomBytes } from './random.js';
11
+ /**
12
+ * Encrypt data with a secret key using NaCl SecretBox.
13
+ *
14
+ * JSON-serializes the data, then encrypts with XSalsa20-Poly1305.
15
+ *
16
+ * @param data - Data to encrypt (will be JSON-serialized)
17
+ * @param secret - 32-byte secret key
18
+ * @returns Bundle: nonce(24) + ciphertext
19
+ */
20
+ export function encryptSecretBox(data, secret) {
21
+ const nonce = getRandomBytes(nacl.secretbox.nonceLength);
22
+ const plaintext = new TextEncoder().encode(JSON.stringify(data));
23
+ const encrypted = nacl.secretbox(plaintext, nonce, secret);
24
+ const result = new Uint8Array(nonce.length + encrypted.length);
25
+ result.set(nonce);
26
+ result.set(encrypted, nonce.length);
27
+ return result;
28
+ }
29
+ /**
30
+ * Decrypt a NaCl SecretBox bundle with a secret key.
31
+ *
32
+ * @param bundle - Bundle: nonce(24) + ciphertext
33
+ * @param secret - 32-byte secret key
34
+ * @returns Deserialized data, or null if decryption fails
35
+ */
36
+ export function decryptSecretBox(bundle, secret) {
37
+ try {
38
+ if (bundle.length < nacl.secretbox.nonceLength)
39
+ return null;
40
+ const nonce = bundle.slice(0, nacl.secretbox.nonceLength);
41
+ const ciphertext = bundle.slice(nacl.secretbox.nonceLength);
42
+ const decrypted = nacl.secretbox.open(ciphertext, nonce, secret);
43
+ if (!decrypted)
44
+ return null;
45
+ return JSON.parse(new TextDecoder().decode(decrypted));
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ }
51
+ //# sourceMappingURL=secretbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretbox.js","sourceRoot":"","sources":["../src/secretbox.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAa,EAAE,MAAkB;IAChE,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAE3D,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClB,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAkB,EAAE,MAAkB;IACrE,IAAI,CAAC;QACH,IAAI,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAE5D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAE5D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACjE,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Session encryption — high-level API composing AES-GCM + NaCl Box.
3
+ *
4
+ * Provides per-session data encryption key (DEK) generation, wrapping,
5
+ * unwrapping, and envelope encrypt/decrypt. Compatible with Happy protocol.
6
+ *
7
+ * Key flow:
8
+ * masterSecret → deriveContentKeyPair → contentPublicKey
9
+ * random DEK (32 bytes) → NaCl Box(DEK, contentPublicKey) → wrappedDek
10
+ * envelope → AES-256-GCM(DEK) → ciphertext (base64)
11
+ */
12
+ /**
13
+ * Generate a per-session data encryption key and wrap it with NaCl Box.
14
+ *
15
+ * 1. Derive content keypair from masterSecret
16
+ * 2. Generate random 32-byte DEK
17
+ * 3. Wrap DEK: NaCl Box(DEK, contentPublicKey)
18
+ * 4. Prepend version byte
19
+ *
20
+ * @param masterSecret - 32-byte master secret shared between daemon and web
21
+ * @returns DEK (for local use) and wrappedDekBase64 (for server storage)
22
+ */
23
+ export declare function generateSessionKeys(masterSecret: Uint8Array): Promise<{
24
+ readonly dek: Uint8Array;
25
+ readonly wrappedDekBase64: string;
26
+ }>;
27
+ /**
28
+ * Unwrap a session DEK using the master secret.
29
+ *
30
+ * 1. Base64-decode the wrapped key
31
+ * 2. Check version byte (must be 0)
32
+ * 3. Derive content keypair from masterSecret
33
+ * 4. Decrypt with NaCl Box using content secret key
34
+ *
35
+ * @param wrappedDekBase64 - Base64-encoded wrapped key from server
36
+ * @param masterSecret - Same master secret used during generation
37
+ * @returns 32-byte DEK, or null if unwrapping fails
38
+ */
39
+ export declare function unwrapSessionKey(wrappedDekBase64: string, masterSecret: Uint8Array): Promise<Uint8Array | null>;
40
+ /**
41
+ * Encrypt a SessionEnvelope (or any JSON-serializable value) for transmission.
42
+ *
43
+ * @param envelope - Data to encrypt (JSON-serializable)
44
+ * @param dek - 32-byte data encryption key
45
+ * @returns Base64-encoded AES-256-GCM ciphertext
46
+ */
47
+ export declare function encryptEnvelope(envelope: unknown, dek: Uint8Array): Promise<string>;
48
+ /**
49
+ * Decrypt a base64-encoded ciphertext back to the original data.
50
+ *
51
+ * @param ciphertextBase64 - Base64-encoded AES-256-GCM bundle
52
+ * @param dek - 32-byte data encryption key
53
+ * @returns Decrypted data, or null if decryption fails
54
+ */
55
+ export declare function decryptEnvelope(ciphertextBase64: string, dek: Uint8Array): Promise<unknown | null>;
56
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,UAAU,GACvB,OAAO,CAAC;IAAE,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC,CAa1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,UAAU,GACvB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAkB5B;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAGzF;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,gBAAgB,EAAE,MAAM,EACxB,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAWzB"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Session encryption — high-level API composing AES-GCM + NaCl Box.
3
+ *
4
+ * Provides per-session data encryption key (DEK) generation, wrapping,
5
+ * unwrapping, and envelope encrypt/decrypt. Compatible with Happy protocol.
6
+ *
7
+ * Key flow:
8
+ * masterSecret → deriveContentKeyPair → contentPublicKey
9
+ * random DEK (32 bytes) → NaCl Box(DEK, contentPublicKey) → wrappedDek
10
+ * envelope → AES-256-GCM(DEK) → ciphertext (base64)
11
+ */
12
+ import { encryptAesGcm, decryptAesGcm } from './aes.js';
13
+ import { encryptBox, decryptBox } from './box.js';
14
+ import { deriveContentKeyPair } from './content.js';
15
+ import { getRandomBytes } from './random.js';
16
+ import { encodeBase64, decodeBase64 } from './encoding.js';
17
+ /** Current wrapped key version. */
18
+ const WRAPPED_KEY_VERSION = 0;
19
+ /** Expected DEK size in bytes. */
20
+ const DEK_SIZE = 32;
21
+ /** Minimum wrapped key bundle size: version(1) + NaCl Box overhead (32+24+16+32). */
22
+ const MIN_WRAPPED_SIZE = 1 + 32 + 24 + DEK_SIZE;
23
+ /**
24
+ * Generate a per-session data encryption key and wrap it with NaCl Box.
25
+ *
26
+ * 1. Derive content keypair from masterSecret
27
+ * 2. Generate random 32-byte DEK
28
+ * 3. Wrap DEK: NaCl Box(DEK, contentPublicKey)
29
+ * 4. Prepend version byte
30
+ *
31
+ * @param masterSecret - 32-byte master secret shared between daemon and web
32
+ * @returns DEK (for local use) and wrappedDekBase64 (for server storage)
33
+ */
34
+ export async function generateSessionKeys(masterSecret) {
35
+ const { publicKey } = await deriveContentKeyPair(masterSecret);
36
+ const dek = getRandomBytes(DEK_SIZE);
37
+ // Wrap DEK with NaCl Box
38
+ const boxBundle = encryptBox(dek, publicKey);
39
+ // Prepend version byte
40
+ const wrapped = new Uint8Array(1 + boxBundle.length);
41
+ wrapped[0] = WRAPPED_KEY_VERSION;
42
+ wrapped.set(boxBundle, 1);
43
+ return { dek, wrappedDekBase64: encodeBase64(wrapped) };
44
+ }
45
+ /**
46
+ * Unwrap a session DEK using the master secret.
47
+ *
48
+ * 1. Base64-decode the wrapped key
49
+ * 2. Check version byte (must be 0)
50
+ * 3. Derive content keypair from masterSecret
51
+ * 4. Decrypt with NaCl Box using content secret key
52
+ *
53
+ * @param wrappedDekBase64 - Base64-encoded wrapped key from server
54
+ * @param masterSecret - Same master secret used during generation
55
+ * @returns 32-byte DEK, or null if unwrapping fails
56
+ */
57
+ export async function unwrapSessionKey(wrappedDekBase64, masterSecret) {
58
+ let wrapped;
59
+ try {
60
+ wrapped = decodeBase64(wrappedDekBase64);
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ if (wrapped.length < MIN_WRAPPED_SIZE)
66
+ return null;
67
+ if (wrapped[0] !== WRAPPED_KEY_VERSION)
68
+ return null;
69
+ const boxBundle = wrapped.slice(1);
70
+ const { secretKey } = await deriveContentKeyPair(masterSecret);
71
+ const dek = decryptBox(boxBundle, secretKey);
72
+ if (!dek || dek.length !== DEK_SIZE)
73
+ return null;
74
+ return dek;
75
+ }
76
+ /**
77
+ * Encrypt a SessionEnvelope (or any JSON-serializable value) for transmission.
78
+ *
79
+ * @param envelope - Data to encrypt (JSON-serializable)
80
+ * @param dek - 32-byte data encryption key
81
+ * @returns Base64-encoded AES-256-GCM ciphertext
82
+ */
83
+ export async function encryptEnvelope(envelope, dek) {
84
+ const bundle = await encryptAesGcm(envelope, dek);
85
+ return encodeBase64(bundle);
86
+ }
87
+ /**
88
+ * Decrypt a base64-encoded ciphertext back to the original data.
89
+ *
90
+ * @param ciphertextBase64 - Base64-encoded AES-256-GCM bundle
91
+ * @param dek - 32-byte data encryption key
92
+ * @returns Decrypted data, or null if decryption fails
93
+ */
94
+ export async function decryptEnvelope(ciphertextBase64, dek) {
95
+ let bundle;
96
+ try {
97
+ bundle = decodeBase64(ciphertextBase64);
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ if (bundle.length === 0)
103
+ return null;
104
+ return decryptAesGcm(bundle, dek);
105
+ }
106
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@agentdock/crypto",
3
+ "version": "0.0.1",
4
+ "description": "E2E encryption for AgentDock — AES-256-GCM, key derivation, Web Crypto API",
5
+ "license": "UNLICENSED",
6
+ "author": "kevin8536945",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public",
21
+ "registry": "https://registry.npmjs.org"
22
+ },
23
+ "dependencies": {
24
+ "tweetnacl": "^1.0.3",
25
+ "@agentdock/wire": "0.0.1"
26
+ },
27
+ "devDependencies": {
28
+ "@vitest/coverage-v8": "^3.0.0",
29
+ "typescript": "^5.7.0",
30
+ "vitest": "^3.0.0"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc",
34
+ "test": "vitest run",
35
+ "test:coverage": "vitest run --coverage",
36
+ "lint": "eslint src/ && tsc --noEmit",
37
+ "typecheck": "tsc --noEmit"
38
+ }
39
+ }