@hashtree/core 0.1.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.
Files changed (138) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bep52.d.ts +179 -0
  3. package/dist/bep52.d.ts.map +1 -0
  4. package/dist/bep52.js +384 -0
  5. package/dist/bep52.js.map +1 -0
  6. package/dist/builder.d.ts +137 -0
  7. package/dist/builder.d.ts.map +1 -0
  8. package/dist/builder.js +281 -0
  9. package/dist/builder.js.map +1 -0
  10. package/dist/codec.d.ts +37 -0
  11. package/dist/codec.d.ts.map +1 -0
  12. package/dist/codec.js +109 -0
  13. package/dist/codec.js.map +1 -0
  14. package/dist/crypto.d.ts +92 -0
  15. package/dist/crypto.d.ts.map +1 -0
  16. package/dist/crypto.js +212 -0
  17. package/dist/crypto.js.map +1 -0
  18. package/dist/encrypted.d.ts +114 -0
  19. package/dist/encrypted.d.ts.map +1 -0
  20. package/dist/encrypted.js +446 -0
  21. package/dist/encrypted.js.map +1 -0
  22. package/dist/hash.d.ts +14 -0
  23. package/dist/hash.d.ts.map +1 -0
  24. package/dist/hash.js +27 -0
  25. package/dist/hash.js.map +1 -0
  26. package/dist/hashtree.d.ts +237 -0
  27. package/dist/hashtree.d.ts.map +1 -0
  28. package/dist/hashtree.js +557 -0
  29. package/dist/hashtree.js.map +1 -0
  30. package/dist/index.d.ts +27 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +44 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/nhash.d.ts +94 -0
  35. package/dist/nhash.d.ts.map +1 -0
  36. package/dist/nhash.js +293 -0
  37. package/dist/nhash.js.map +1 -0
  38. package/dist/resolver/index.d.ts +5 -0
  39. package/dist/resolver/index.d.ts.map +1 -0
  40. package/dist/resolver/index.js +5 -0
  41. package/dist/resolver/index.js.map +1 -0
  42. package/dist/resolver/nostr.d.ts +82 -0
  43. package/dist/resolver/nostr.d.ts.map +1 -0
  44. package/dist/resolver/nostr.js +868 -0
  45. package/dist/resolver/nostr.js.map +1 -0
  46. package/dist/store/blossom.d.ts +100 -0
  47. package/dist/store/blossom.d.ts.map +1 -0
  48. package/dist/store/blossom.js +355 -0
  49. package/dist/store/blossom.js.map +1 -0
  50. package/dist/store/dexie.d.ts +44 -0
  51. package/dist/store/dexie.d.ts.map +1 -0
  52. package/dist/store/dexie.js +196 -0
  53. package/dist/store/dexie.js.map +1 -0
  54. package/dist/store/fallback.d.ts +40 -0
  55. package/dist/store/fallback.d.ts.map +1 -0
  56. package/dist/store/fallback.js +71 -0
  57. package/dist/store/fallback.js.map +1 -0
  58. package/dist/store/index.d.ts +6 -0
  59. package/dist/store/index.d.ts.map +1 -0
  60. package/dist/store/index.js +6 -0
  61. package/dist/store/index.js.map +1 -0
  62. package/dist/store/memory.d.ts +29 -0
  63. package/dist/store/memory.d.ts.map +1 -0
  64. package/dist/store/memory.js +66 -0
  65. package/dist/store/memory.js.map +1 -0
  66. package/dist/store/opfs.d.ts +56 -0
  67. package/dist/store/opfs.d.ts.map +1 -0
  68. package/dist/store/opfs.js +200 -0
  69. package/dist/store/opfs.js.map +1 -0
  70. package/dist/streaming.d.ts +74 -0
  71. package/dist/streaming.d.ts.map +1 -0
  72. package/dist/streaming.js +199 -0
  73. package/dist/streaming.js.map +1 -0
  74. package/dist/tree/create.d.ts +35 -0
  75. package/dist/tree/create.d.ts.map +1 -0
  76. package/dist/tree/create.js +90 -0
  77. package/dist/tree/create.js.map +1 -0
  78. package/dist/tree/edit.d.ts +28 -0
  79. package/dist/tree/edit.d.ts.map +1 -0
  80. package/dist/tree/edit.js +115 -0
  81. package/dist/tree/edit.js.map +1 -0
  82. package/dist/tree/editEncrypted.d.ts +46 -0
  83. package/dist/tree/editEncrypted.d.ts.map +1 -0
  84. package/dist/tree/editEncrypted.js +225 -0
  85. package/dist/tree/editEncrypted.js.map +1 -0
  86. package/dist/tree/index.d.ts +7 -0
  87. package/dist/tree/index.d.ts.map +1 -0
  88. package/dist/tree/index.js +7 -0
  89. package/dist/tree/index.js.map +1 -0
  90. package/dist/tree/read.d.ts +75 -0
  91. package/dist/tree/read.d.ts.map +1 -0
  92. package/dist/tree/read.js +389 -0
  93. package/dist/tree/read.js.map +1 -0
  94. package/dist/tree/writeAt.d.ts +44 -0
  95. package/dist/tree/writeAt.d.ts.map +1 -0
  96. package/dist/tree/writeAt.js +282 -0
  97. package/dist/tree/writeAt.js.map +1 -0
  98. package/dist/types.d.ts +274 -0
  99. package/dist/types.d.ts.map +1 -0
  100. package/dist/types.js +47 -0
  101. package/dist/types.js.map +1 -0
  102. package/dist/verify.d.ts +12 -0
  103. package/dist/verify.d.ts.map +1 -0
  104. package/dist/verify.js +32 -0
  105. package/dist/verify.js.map +1 -0
  106. package/dist/visibility.d.ts +50 -0
  107. package/dist/visibility.d.ts.map +1 -0
  108. package/dist/visibility.js +111 -0
  109. package/dist/visibility.js.map +1 -0
  110. package/dist/webrtc/index.d.ts +4 -0
  111. package/dist/webrtc/index.d.ts.map +1 -0
  112. package/dist/webrtc/index.js +4 -0
  113. package/dist/webrtc/index.js.map +1 -0
  114. package/dist/webrtc/lruCache.d.ts +20 -0
  115. package/dist/webrtc/lruCache.d.ts.map +1 -0
  116. package/dist/webrtc/lruCache.js +59 -0
  117. package/dist/webrtc/lruCache.js.map +1 -0
  118. package/dist/webrtc/peer.d.ts +122 -0
  119. package/dist/webrtc/peer.d.ts.map +1 -0
  120. package/dist/webrtc/peer.js +583 -0
  121. package/dist/webrtc/peer.js.map +1 -0
  122. package/dist/webrtc/protocol.d.ts +76 -0
  123. package/dist/webrtc/protocol.d.ts.map +1 -0
  124. package/dist/webrtc/protocol.js +167 -0
  125. package/dist/webrtc/protocol.js.map +1 -0
  126. package/dist/webrtc/store.d.ts +190 -0
  127. package/dist/webrtc/store.d.ts.map +1 -0
  128. package/dist/webrtc/store.js +1043 -0
  129. package/dist/webrtc/store.js.map +1 -0
  130. package/dist/webrtc/types.d.ts +196 -0
  131. package/dist/webrtc/types.d.ts.map +1 -0
  132. package/dist/webrtc/types.js +46 -0
  133. package/dist/webrtc/types.js.map +1 -0
  134. package/dist/worker/protocol.d.ts +493 -0
  135. package/dist/worker/protocol.d.ts.map +1 -0
  136. package/dist/worker/protocol.js +15 -0
  137. package/dist/worker/protocol.js.map +1 -0
  138. package/package.json +59 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,wCAAwC;AACxC,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC;AAoBvC,+CAA+C;AAC/C,wBAAgB,WAAW,IAAI,aAAa,CAI3C;AAmDD;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAE1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,aAAa,CAAA;CAAE,CAAC,CAyB/G;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAyBhG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CA0B5F;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAoB5F;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,gCAAgC;AAChC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAEnD;AAED,gCAAgC;AAChC,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CASrD"}
package/dist/crypto.js ADDED
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Encryption utilities for HashTree
3
+ *
4
+ * CHK (Content Hash Key) encryption for deterministic encryption:
5
+ * - key = SHA256(plaintext) - content hash becomes decryption key
6
+ * - encryption_key = HKDF(key, salt="hashtree-chk", info="encryption-key")
7
+ * - ciphertext = AES-256-GCM(encryption_key, zero_nonce, plaintext)
8
+ *
9
+ * Zero nonce is safe because CHK guarantees: same key = same content.
10
+ * This enables deduplication: same content → same ciphertext → same hash.
11
+ *
12
+ * Format: [ciphertext][16-byte auth tag] (no IV needed with CHK)
13
+ *
14
+ * Also includes legacy functions with random IV for backward compatibility:
15
+ * Format: [12-byte IV][ciphertext][16-byte auth tag]
16
+ */
17
+ import { sha256 } from './hash.js';
18
+ /** IV/Nonce size for AES-GCM */
19
+ const IV_SIZE = 12;
20
+ /** Auth tag size for AES-GCM */
21
+ const TAG_SIZE = 16;
22
+ /** Minimum encrypted data size: IV + tag (for legacy format) */
23
+ const MIN_ENCRYPTED_SIZE = IV_SIZE + TAG_SIZE;
24
+ /** Minimum CHK encrypted size: just tag (no IV) */
25
+ const MIN_CHK_ENCRYPTED_SIZE = TAG_SIZE;
26
+ /** HKDF salt for CHK key derivation */
27
+ const CHK_SALT = new TextEncoder().encode('hashtree-chk');
28
+ /** HKDF info for CHK key derivation */
29
+ const CHK_INFO = new TextEncoder().encode('encryption-key');
30
+ /** Generate a random 32-byte encryption key */
31
+ export function generateKey() {
32
+ const key = new Uint8Array(32);
33
+ crypto.getRandomValues(key);
34
+ return key;
35
+ }
36
+ /**
37
+ * Import raw key bytes as CryptoKey for AES-GCM
38
+ */
39
+ async function importKey(key) {
40
+ // Copy to ensure we have a clean ArrayBuffer (not SharedArrayBuffer)
41
+ const keyBuffer = new ArrayBuffer(key.length);
42
+ new Uint8Array(keyBuffer).set(key);
43
+ return crypto.subtle.importKey('raw', keyBuffer, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
44
+ }
45
+ /**
46
+ * Derive AES key from content hash using HKDF
47
+ * @param contentHash - 32-byte content hash (SHA256 of plaintext)
48
+ * @returns 32-byte derived encryption key
49
+ */
50
+ async function deriveKey(contentHash) {
51
+ // Import content hash as HKDF key material
52
+ const keyBuffer = new ArrayBuffer(contentHash.length);
53
+ new Uint8Array(keyBuffer).set(contentHash);
54
+ const hkdfKey = await crypto.subtle.importKey('raw', keyBuffer, { name: 'HKDF' }, false, ['deriveKey']);
55
+ // Derive AES-GCM key using HKDF
56
+ return crypto.subtle.deriveKey({
57
+ name: 'HKDF',
58
+ salt: CHK_SALT,
59
+ info: CHK_INFO,
60
+ hash: 'SHA-256',
61
+ }, hkdfKey, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
62
+ }
63
+ /**
64
+ * Compute content hash (SHA256) - this becomes the decryption key for CHK
65
+ */
66
+ export async function contentHash(data) {
67
+ return sha256(data);
68
+ }
69
+ /**
70
+ * CHK encrypt: derive key from content, encrypt with zero nonce
71
+ *
72
+ * Returns: (ciphertext with auth tag, content_hash as decryption key)
73
+ *
74
+ * Zero nonce is safe because CHK guarantees: same key = same content.
75
+ * We never encrypt different content with the same key.
76
+ *
77
+ * The content_hash is both:
78
+ * - The decryption key (store securely, share with authorized users)
79
+ * - Enables dedup: same content → same ciphertext
80
+ *
81
+ * @param plaintext - Data to encrypt
82
+ * @returns Object with encrypted data and content hash (decryption key)
83
+ */
84
+ export async function encryptChk(plaintext) {
85
+ // 1. Compute content hash - this is the "key" we return
86
+ const chash = await contentHash(plaintext);
87
+ // 2. Derive actual encryption key from content hash via HKDF
88
+ const cryptoKey = await deriveKey(chash);
89
+ // 3. Zero nonce - safe because same key = same content with CHK
90
+ const zeroNonce = new Uint8Array(IV_SIZE);
91
+ // 4. Copy plaintext to clean ArrayBuffer for WebCrypto
92
+ const plaintextBuffer = new ArrayBuffer(plaintext.length);
93
+ new Uint8Array(plaintextBuffer).set(plaintext);
94
+ // 5. Encrypt
95
+ const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: zeroNonce }, cryptoKey, plaintextBuffer);
96
+ return {
97
+ ciphertext: new Uint8Array(ciphertext),
98
+ key: chash
99
+ };
100
+ }
101
+ /**
102
+ * CHK decrypt: derive key from content_hash, decrypt with zero nonce
103
+ *
104
+ * @param ciphertext - Encrypted data (includes auth tag)
105
+ * @param key - Content hash returned from encryptChk
106
+ * @returns Decrypted plaintext
107
+ * @throws Error if decryption fails (wrong key or tampered data)
108
+ */
109
+ export async function decryptChk(ciphertext, key) {
110
+ if (key.length !== 32) {
111
+ throw new Error('CHK key must be 32 bytes');
112
+ }
113
+ if (ciphertext.length < MIN_CHK_ENCRYPTED_SIZE) {
114
+ throw new Error('CHK encrypted data too short');
115
+ }
116
+ // Derive encryption key from content hash
117
+ const cryptoKey = await deriveKey(key);
118
+ // Zero nonce
119
+ const zeroNonce = new Uint8Array(IV_SIZE);
120
+ // Copy ciphertext to clean ArrayBuffer for WebCrypto
121
+ const ciphertextBuffer = new ArrayBuffer(ciphertext.length);
122
+ new Uint8Array(ciphertextBuffer).set(ciphertext);
123
+ const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: zeroNonce }, cryptoKey, ciphertextBuffer);
124
+ return new Uint8Array(plaintext);
125
+ }
126
+ /**
127
+ * Calculate encrypted size for CHK (no nonce prefix, just ciphertext + auth tag)
128
+ */
129
+ export function encryptedSizeChk(plaintextSize) {
130
+ return plaintextSize + TAG_SIZE;
131
+ }
132
+ /**
133
+ * Encrypt data using AES-256-GCM with random IV
134
+ * @deprecated Use encryptChk for deterministic CHK encryption
135
+ *
136
+ * @param plaintext - Data to encrypt
137
+ * @param key - 32-byte encryption key
138
+ * @returns Encrypted data: [12-byte IV][ciphertext + 16-byte auth tag]
139
+ */
140
+ export async function encrypt(plaintext, key) {
141
+ if (key.length !== 32) {
142
+ throw new Error('Encryption key must be 32 bytes');
143
+ }
144
+ const iv = new Uint8Array(IV_SIZE);
145
+ crypto.getRandomValues(iv);
146
+ const cryptoKey = await importKey(key);
147
+ // Copy plaintext to clean ArrayBuffer for WebCrypto
148
+ const plaintextBuffer = new ArrayBuffer(plaintext.length);
149
+ new Uint8Array(plaintextBuffer).set(plaintext);
150
+ const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, cryptoKey, plaintextBuffer);
151
+ // Prepend IV to ciphertext
152
+ const result = new Uint8Array(IV_SIZE + ciphertext.byteLength);
153
+ result.set(iv, 0);
154
+ result.set(new Uint8Array(ciphertext), IV_SIZE);
155
+ return result;
156
+ }
157
+ /**
158
+ * Decrypt data using AES-256-GCM
159
+ *
160
+ * @param encrypted - Encrypted data: [12-byte IV][ciphertext + auth tag]
161
+ * @param key - 32-byte encryption key
162
+ * @returns Decrypted plaintext
163
+ * @throws Error if decryption fails (wrong key or tampered data)
164
+ */
165
+ export async function decrypt(encrypted, key) {
166
+ if (key.length !== 32) {
167
+ throw new Error('Encryption key must be 32 bytes');
168
+ }
169
+ if (encrypted.length < MIN_ENCRYPTED_SIZE) {
170
+ throw new Error('Encrypted data too short');
171
+ }
172
+ const iv = encrypted.slice(0, IV_SIZE);
173
+ const ciphertext = encrypted.slice(IV_SIZE);
174
+ const cryptoKey = await importKey(key);
175
+ const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, cryptoKey, ciphertext);
176
+ return new Uint8Array(plaintext);
177
+ }
178
+ /**
179
+ * Check if data could be encrypted (based on minimum size).
180
+ * Note: This is a heuristic - actual encrypted data might be larger.
181
+ */
182
+ export function couldBeEncrypted(data) {
183
+ return data.length >= MIN_ENCRYPTED_SIZE;
184
+ }
185
+ /**
186
+ * Calculate encrypted size for given plaintext size
187
+ */
188
+ export function encryptedSize(plaintextSize) {
189
+ return IV_SIZE + plaintextSize + TAG_SIZE;
190
+ }
191
+ /**
192
+ * Calculate plaintext size from encrypted size
193
+ */
194
+ export function plaintextSize(encryptedSize) {
195
+ return Math.max(0, encryptedSize - IV_SIZE - TAG_SIZE);
196
+ }
197
+ /** Convert key to hex string */
198
+ export function keyToHex(key) {
199
+ return Array.from(key).map(b => b.toString(16).padStart(2, '0')).join('');
200
+ }
201
+ /** Convert hex string to key */
202
+ export function keyFromHex(hex) {
203
+ if (hex.length !== 64) {
204
+ throw new Error('Key hex must be 64 characters (32 bytes)');
205
+ }
206
+ const key = new Uint8Array(32);
207
+ for (let i = 0; i < 32; i++) {
208
+ key[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
209
+ }
210
+ return key;
211
+ }
212
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * CHK (Content Hash Key) encrypted file operations for HashTree
3
+ *
4
+ * Everything uses CHK encryption:
5
+ * - Chunks: key = SHA256(plaintext)
6
+ * - Tree nodes: key = SHA256(msgpack_encoded_node)
7
+ *
8
+ * Same content → same ciphertext → deduplication works at all levels.
9
+ * The root key is deterministic: same file = same CID (hash + key).
10
+ */
11
+ import { Store, Hash, TreeNode, LinkType } from './types.js';
12
+ import { type EncryptionKey } from './crypto.js';
13
+ export interface EncryptedTreeConfig {
14
+ store: Store;
15
+ chunkSize: number;
16
+ }
17
+ /**
18
+ * Result of encrypted file storage
19
+ */
20
+ export interface EncryptedPutResult {
21
+ /** Root hash of encrypted tree */
22
+ hash: Hash;
23
+ /** Original plaintext size */
24
+ size: number;
25
+ /** Encryption key for the root (content hash for CHK) */
26
+ key: EncryptionKey;
27
+ }
28
+ /**
29
+ * Store a file with CHK encryption
30
+ *
31
+ * Everything is CHK encrypted - deterministic, enables full deduplication.
32
+ * Returns hash + key, both derived from content.
33
+ *
34
+ * @param config - Tree configuration
35
+ * @param data - File data to encrypt and store
36
+ * @returns Hash of encrypted root and the encryption key (content hash)
37
+ */
38
+ export declare function putFileEncrypted(config: EncryptedTreeConfig, data: Uint8Array): Promise<EncryptedPutResult>;
39
+ /**
40
+ * Read an encrypted file
41
+ *
42
+ * Key is always the CHK key (content hash of plaintext)
43
+ *
44
+ * @param store - Storage backend
45
+ * @param hash - Root hash of encrypted file
46
+ * @param key - CHK decryption key (content hash)
47
+ * @returns Decrypted file data
48
+ */
49
+ export declare function readFileEncrypted(store: Store, hash: Hash, key: EncryptionKey): Promise<Uint8Array | null>;
50
+ export interface StreamOptions {
51
+ /** Byte offset to start streaming from (default: 0) */
52
+ offset?: number;
53
+ /** Number of chunks to prefetch ahead (default: 1 = no prefetch) */
54
+ prefetch?: number;
55
+ }
56
+ /**
57
+ * Stream an encrypted file
58
+ * @param store - Storage backend
59
+ * @param hash - Root hash of encrypted file
60
+ * @param key - CHK decryption key (content hash)
61
+ * @param options - Streaming options
62
+ */
63
+ export declare function readFileEncryptedStream(store: Store, hash: Hash, key: EncryptionKey, options?: StreamOptions): AsyncGenerator<Uint8Array>;
64
+ /**
65
+ * Read a range of bytes from an encrypted file
66
+ */
67
+ export declare function readFileEncryptedRange(store: Store, hash: Hash, key: EncryptionKey, start: number, end?: number): Promise<Uint8Array | null>;
68
+ /**
69
+ * Directory entry with optional encryption key
70
+ */
71
+ export interface EncryptedDirEntry {
72
+ name: string;
73
+ hash: Hash;
74
+ size: number;
75
+ /** CHK key for encrypted children */
76
+ key?: Uint8Array;
77
+ /** Type of this entry: Blob, File, or Dir */
78
+ type: LinkType;
79
+ /** Optional metadata (createdAt, mimeType, thumbnail, etc.) */
80
+ meta?: Record<string, unknown>;
81
+ }
82
+ /**
83
+ * Store a directory with CHK encryption
84
+ *
85
+ * The directory node itself is encrypted. Child entries already have their own keys.
86
+ * Large directories are chunked by bytes like files using putFileEncrypted.
87
+ *
88
+ * @param config - Tree configuration
89
+ * @param entries - Directory entries (with keys for encrypted children)
90
+ * @returns Hash of encrypted directory and the encryption key
91
+ */
92
+ export declare function putDirectoryEncrypted(config: EncryptedTreeConfig, entries: EncryptedDirEntry[]): Promise<EncryptedPutResult>;
93
+ /**
94
+ * List directory entries from an encrypted directory
95
+ *
96
+ * Handles both small directories (single node) and large directories
97
+ * (chunked by bytes like files).
98
+ *
99
+ * @param store - Storage backend
100
+ * @param hash - Hash of encrypted directory
101
+ * @param key - CHK decryption key
102
+ * @returns Directory entries with their encryption keys
103
+ */
104
+ export declare function listDirectoryEncrypted(store: Store, hash: Hash, key: EncryptionKey): Promise<EncryptedDirEntry[]>;
105
+ /**
106
+ * Get a tree node from encrypted storage
107
+ *
108
+ * @param store - Storage backend
109
+ * @param hash - Hash of encrypted node
110
+ * @param key - CHK decryption key
111
+ * @returns Decrypted tree node
112
+ */
113
+ export declare function getTreeNodeEncrypted(store: Store, hash: Hash, key: EncryptionKey): Promise<TreeNode | null>;
114
+ //# sourceMappingURL=encrypted.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypted.d.ts","sourceRoot":"","sources":["../src/encrypted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAQ,QAAQ,EAAS,MAAM,YAAY,CAAC;AAG1E,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,IAAI,EAAE,IAAI,CAAC;IACX,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,GAAG,EAAE,aAAa,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,kBAAkB,CAAC,CAqC7B;AAiCD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAe5B;AAmFD,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAuB,uBAAuB,CAC5C,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,aAAkB,GAC1B,cAAc,CAAC,UAAU,CAAC,CAiB5B;AA4GD;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAe5B;AAmFD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,6CAA6C;IAC7C,IAAI,EAAE,QAAQ,CAAC;IACf,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,iBAAiB,EAAE,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CA+B7B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAoB9B;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAO1B"}