@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.
- package/LICENSE +21 -0
- package/dist/bep52.d.ts +179 -0
- package/dist/bep52.d.ts.map +1 -0
- package/dist/bep52.js +384 -0
- package/dist/bep52.js.map +1 -0
- package/dist/builder.d.ts +137 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +281 -0
- package/dist/builder.js.map +1 -0
- package/dist/codec.d.ts +37 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +109 -0
- package/dist/codec.js.map +1 -0
- package/dist/crypto.d.ts +92 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +212 -0
- package/dist/crypto.js.map +1 -0
- package/dist/encrypted.d.ts +114 -0
- package/dist/encrypted.d.ts.map +1 -0
- package/dist/encrypted.js +446 -0
- package/dist/encrypted.js.map +1 -0
- package/dist/hash.d.ts +14 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +27 -0
- package/dist/hash.js.map +1 -0
- package/dist/hashtree.d.ts +237 -0
- package/dist/hashtree.d.ts.map +1 -0
- package/dist/hashtree.js +557 -0
- package/dist/hashtree.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/nhash.d.ts +94 -0
- package/dist/nhash.d.ts.map +1 -0
- package/dist/nhash.js +293 -0
- package/dist/nhash.js.map +1 -0
- package/dist/resolver/index.d.ts +5 -0
- package/dist/resolver/index.d.ts.map +1 -0
- package/dist/resolver/index.js +5 -0
- package/dist/resolver/index.js.map +1 -0
- package/dist/resolver/nostr.d.ts +82 -0
- package/dist/resolver/nostr.d.ts.map +1 -0
- package/dist/resolver/nostr.js +868 -0
- package/dist/resolver/nostr.js.map +1 -0
- package/dist/store/blossom.d.ts +100 -0
- package/dist/store/blossom.d.ts.map +1 -0
- package/dist/store/blossom.js +355 -0
- package/dist/store/blossom.js.map +1 -0
- package/dist/store/dexie.d.ts +44 -0
- package/dist/store/dexie.d.ts.map +1 -0
- package/dist/store/dexie.js +196 -0
- package/dist/store/dexie.js.map +1 -0
- package/dist/store/fallback.d.ts +40 -0
- package/dist/store/fallback.d.ts.map +1 -0
- package/dist/store/fallback.js +71 -0
- package/dist/store/fallback.js.map +1 -0
- package/dist/store/index.d.ts +6 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +6 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/memory.d.ts +29 -0
- package/dist/store/memory.d.ts.map +1 -0
- package/dist/store/memory.js +66 -0
- package/dist/store/memory.js.map +1 -0
- package/dist/store/opfs.d.ts +56 -0
- package/dist/store/opfs.d.ts.map +1 -0
- package/dist/store/opfs.js +200 -0
- package/dist/store/opfs.js.map +1 -0
- package/dist/streaming.d.ts +74 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +199 -0
- package/dist/streaming.js.map +1 -0
- package/dist/tree/create.d.ts +35 -0
- package/dist/tree/create.d.ts.map +1 -0
- package/dist/tree/create.js +90 -0
- package/dist/tree/create.js.map +1 -0
- package/dist/tree/edit.d.ts +28 -0
- package/dist/tree/edit.d.ts.map +1 -0
- package/dist/tree/edit.js +115 -0
- package/dist/tree/edit.js.map +1 -0
- package/dist/tree/editEncrypted.d.ts +46 -0
- package/dist/tree/editEncrypted.d.ts.map +1 -0
- package/dist/tree/editEncrypted.js +225 -0
- package/dist/tree/editEncrypted.js.map +1 -0
- package/dist/tree/index.d.ts +7 -0
- package/dist/tree/index.d.ts.map +1 -0
- package/dist/tree/index.js +7 -0
- package/dist/tree/index.js.map +1 -0
- package/dist/tree/read.d.ts +75 -0
- package/dist/tree/read.d.ts.map +1 -0
- package/dist/tree/read.js +389 -0
- package/dist/tree/read.js.map +1 -0
- package/dist/tree/writeAt.d.ts +44 -0
- package/dist/tree/writeAt.d.ts.map +1 -0
- package/dist/tree/writeAt.js +282 -0
- package/dist/tree/writeAt.js.map +1 -0
- package/dist/types.d.ts +274 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +47 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +12 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +32 -0
- package/dist/verify.js.map +1 -0
- package/dist/visibility.d.ts +50 -0
- package/dist/visibility.d.ts.map +1 -0
- package/dist/visibility.js +111 -0
- package/dist/visibility.js.map +1 -0
- package/dist/webrtc/index.d.ts +4 -0
- package/dist/webrtc/index.d.ts.map +1 -0
- package/dist/webrtc/index.js +4 -0
- package/dist/webrtc/index.js.map +1 -0
- package/dist/webrtc/lruCache.d.ts +20 -0
- package/dist/webrtc/lruCache.d.ts.map +1 -0
- package/dist/webrtc/lruCache.js +59 -0
- package/dist/webrtc/lruCache.js.map +1 -0
- package/dist/webrtc/peer.d.ts +122 -0
- package/dist/webrtc/peer.d.ts.map +1 -0
- package/dist/webrtc/peer.js +583 -0
- package/dist/webrtc/peer.js.map +1 -0
- package/dist/webrtc/protocol.d.ts +76 -0
- package/dist/webrtc/protocol.d.ts.map +1 -0
- package/dist/webrtc/protocol.js +167 -0
- package/dist/webrtc/protocol.js.map +1 -0
- package/dist/webrtc/store.d.ts +190 -0
- package/dist/webrtc/store.d.ts.map +1 -0
- package/dist/webrtc/store.js +1043 -0
- package/dist/webrtc/store.js.map +1 -0
- package/dist/webrtc/types.d.ts +196 -0
- package/dist/webrtc/types.d.ts.map +1 -0
- package/dist/webrtc/types.js +46 -0
- package/dist/webrtc/types.js.map +1 -0
- package/dist/worker/protocol.d.ts +493 -0
- package/dist/worker/protocol.d.ts.map +1 -0
- package/dist/worker/protocol.js +15 -0
- package/dist/worker/protocol.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,446 @@
|
|
|
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 { LinkType, toHex } from './types.js';
|
|
12
|
+
import { sha256 } from './hash.js';
|
|
13
|
+
import { encodeAndHash, decodeTreeNode, tryDecodeTreeNode } from './codec.js';
|
|
14
|
+
import { encryptChk, decryptChk } from './crypto.js';
|
|
15
|
+
/**
|
|
16
|
+
* Store a file with CHK encryption
|
|
17
|
+
*
|
|
18
|
+
* Everything is CHK encrypted - deterministic, enables full deduplication.
|
|
19
|
+
* Returns hash + key, both derived from content.
|
|
20
|
+
*
|
|
21
|
+
* @param config - Tree configuration
|
|
22
|
+
* @param data - File data to encrypt and store
|
|
23
|
+
* @returns Hash of encrypted root and the encryption key (content hash)
|
|
24
|
+
*/
|
|
25
|
+
export async function putFileEncrypted(config, data) {
|
|
26
|
+
const { store, chunkSize } = config;
|
|
27
|
+
const size = data.length;
|
|
28
|
+
// Single chunk - use CHK directly
|
|
29
|
+
if (data.length <= chunkSize) {
|
|
30
|
+
const { ciphertext, key } = await encryptChk(data);
|
|
31
|
+
const hash = await sha256(ciphertext);
|
|
32
|
+
await store.put(hash, ciphertext);
|
|
33
|
+
return { hash, size, key };
|
|
34
|
+
}
|
|
35
|
+
// Process chunks sequentially to avoid memory spikes
|
|
36
|
+
// (For parallel processing of large files, use StreamWriter instead)
|
|
37
|
+
const links = [];
|
|
38
|
+
let offset = 0;
|
|
39
|
+
while (offset < data.length) {
|
|
40
|
+
const end = Math.min(offset + chunkSize, data.length);
|
|
41
|
+
// Use subarray to avoid copying, encrypt will handle the data
|
|
42
|
+
const chunk = data.subarray(offset, end);
|
|
43
|
+
const { ciphertext, key: chunkKey } = await encryptChk(chunk);
|
|
44
|
+
const hash = await sha256(ciphertext);
|
|
45
|
+
await store.put(hash, ciphertext);
|
|
46
|
+
links.push({
|
|
47
|
+
hash,
|
|
48
|
+
// Store PLAINTEXT size in link for correct range seeking
|
|
49
|
+
size: chunk.length,
|
|
50
|
+
key: chunkKey,
|
|
51
|
+
type: LinkType.Blob,
|
|
52
|
+
});
|
|
53
|
+
offset = end;
|
|
54
|
+
}
|
|
55
|
+
// Build tree - tree nodes also CHK encrypted
|
|
56
|
+
const { hash: rootHash, key: rootKey } = await buildEncryptedTree(config, links, size);
|
|
57
|
+
return { hash: rootHash, size, key: rootKey };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build tree structure with CHK-encrypted tree nodes
|
|
61
|
+
* Returns hash and key for the root node
|
|
62
|
+
*/
|
|
63
|
+
async function buildEncryptedTree(config, links, totalSize) {
|
|
64
|
+
const { store } = config;
|
|
65
|
+
// Single link - return its hash and key directly
|
|
66
|
+
if (links.length === 1 && links[0].key) {
|
|
67
|
+
if (totalSize !== undefined && links[0].size === totalSize) {
|
|
68
|
+
return { hash: links[0].hash, key: links[0].key };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Create single flat node with all links
|
|
72
|
+
const node = {
|
|
73
|
+
type: LinkType.File,
|
|
74
|
+
links,
|
|
75
|
+
};
|
|
76
|
+
const { data } = await encodeAndHash(node);
|
|
77
|
+
// CHK encrypt the tree node
|
|
78
|
+
const { ciphertext, key: nodeKey } = await encryptChk(data);
|
|
79
|
+
const hash = await sha256(ciphertext);
|
|
80
|
+
await store.put(hash, ciphertext);
|
|
81
|
+
return { hash, key: nodeKey };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Read an encrypted file
|
|
85
|
+
*
|
|
86
|
+
* Key is always the CHK key (content hash of plaintext)
|
|
87
|
+
*
|
|
88
|
+
* @param store - Storage backend
|
|
89
|
+
* @param hash - Root hash of encrypted file
|
|
90
|
+
* @param key - CHK decryption key (content hash)
|
|
91
|
+
* @returns Decrypted file data
|
|
92
|
+
*/
|
|
93
|
+
export async function readFileEncrypted(store, hash, key) {
|
|
94
|
+
const encryptedData = await store.get(hash);
|
|
95
|
+
if (!encryptedData)
|
|
96
|
+
return null;
|
|
97
|
+
// CHK decrypt
|
|
98
|
+
const decrypted = await decryptChk(encryptedData, key);
|
|
99
|
+
// Check if it's a tree node
|
|
100
|
+
const node = tryDecodeTreeNode(decrypted);
|
|
101
|
+
if (node) {
|
|
102
|
+
return assembleEncryptedChunks(store, node);
|
|
103
|
+
}
|
|
104
|
+
// Single chunk data
|
|
105
|
+
return decrypted;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get directory node from encrypted storage, handling chunked directories
|
|
109
|
+
*/
|
|
110
|
+
async function getEncryptedDirectoryNode(store, hash, key) {
|
|
111
|
+
const encryptedData = await store.get(hash);
|
|
112
|
+
if (!encryptedData)
|
|
113
|
+
return null;
|
|
114
|
+
const decrypted = await decryptChk(encryptedData, key);
|
|
115
|
+
// Check if it's directly a directory (small directory)
|
|
116
|
+
const node = tryDecodeTreeNode(decrypted);
|
|
117
|
+
if (node?.type === LinkType.Dir) {
|
|
118
|
+
return node;
|
|
119
|
+
}
|
|
120
|
+
// It's a chunk tree - could be a chunked directory
|
|
121
|
+
if (node) {
|
|
122
|
+
const assembled = await assembleEncryptedChunks(store, node);
|
|
123
|
+
// Check if assembled result is a directory
|
|
124
|
+
const assembledNode = tryDecodeTreeNode(assembled);
|
|
125
|
+
if (assembledNode?.type === LinkType.Dir) {
|
|
126
|
+
return assembledNode;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return null; // Not a directory
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Assemble chunks from an encrypted tree
|
|
133
|
+
* Each link has its own CHK key
|
|
134
|
+
* Fetches all children in parallel within each tree level
|
|
135
|
+
*/
|
|
136
|
+
async function assembleEncryptedChunks(store, node) {
|
|
137
|
+
// Fetch and decrypt all children in parallel
|
|
138
|
+
const childPromises = node.links.map(async (link) => {
|
|
139
|
+
const chunkKey = link.key;
|
|
140
|
+
if (!chunkKey) {
|
|
141
|
+
throw new Error(`Missing decryption key for chunk: ${toHex(link.hash)}`);
|
|
142
|
+
}
|
|
143
|
+
const encryptedChild = await store.get(link.hash);
|
|
144
|
+
if (!encryptedChild) {
|
|
145
|
+
throw new Error(`Missing chunk: ${toHex(link.hash)}`);
|
|
146
|
+
}
|
|
147
|
+
const decrypted = await decryptChk(encryptedChild, chunkKey);
|
|
148
|
+
if (link.type !== LinkType.Blob) {
|
|
149
|
+
// Intermediate tree node - decode and recurse (parallel recursion)
|
|
150
|
+
const childNode = decodeTreeNode(decrypted);
|
|
151
|
+
return assembleEncryptedChunks(store, childNode);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// Leaf data chunk - raw blob
|
|
155
|
+
return decrypted;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
// Wait for all children to complete
|
|
159
|
+
const parts = await Promise.all(childPromises);
|
|
160
|
+
const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
|
|
161
|
+
const result = new Uint8Array(totalLength);
|
|
162
|
+
let offset = 0;
|
|
163
|
+
for (const part of parts) {
|
|
164
|
+
result.set(part, offset);
|
|
165
|
+
offset += part.length;
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Stream an encrypted file
|
|
171
|
+
* @param store - Storage backend
|
|
172
|
+
* @param hash - Root hash of encrypted file
|
|
173
|
+
* @param key - CHK decryption key (content hash)
|
|
174
|
+
* @param options - Streaming options
|
|
175
|
+
*/
|
|
176
|
+
export async function* readFileEncryptedStream(store, hash, key, options = {}) {
|
|
177
|
+
const { offset = 0, prefetch = 1 } = options;
|
|
178
|
+
const encryptedData = await store.get(hash);
|
|
179
|
+
if (!encryptedData)
|
|
180
|
+
return;
|
|
181
|
+
// CHK decrypt
|
|
182
|
+
const decrypted = await decryptChk(encryptedData, key);
|
|
183
|
+
const node = tryDecodeTreeNode(decrypted);
|
|
184
|
+
if (node) {
|
|
185
|
+
yield* streamEncryptedChunksWithOffset(store, node, offset, prefetch);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Single blob (small file)
|
|
189
|
+
if (offset >= decrypted.length)
|
|
190
|
+
return;
|
|
191
|
+
yield offset > 0 ? decrypted.slice(offset) : decrypted;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Stream encrypted chunks starting from an offset with prefetching
|
|
196
|
+
*/
|
|
197
|
+
async function* streamEncryptedChunksWithOffset(store, node, offset, prefetch = 1) {
|
|
198
|
+
let position = 0;
|
|
199
|
+
// Find first link index that we need (skip those before offset)
|
|
200
|
+
let startIdx = 0;
|
|
201
|
+
for (let i = 0; i < node.links.length; i++) {
|
|
202
|
+
const linkSize = node.links[i].size ?? 0;
|
|
203
|
+
if (linkSize > 0 && position + linkSize <= offset) {
|
|
204
|
+
position += linkSize;
|
|
205
|
+
startIdx = i + 1;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Build list of links to process
|
|
212
|
+
const linksToProcess = node.links.slice(startIdx);
|
|
213
|
+
if (linksToProcess.length === 0)
|
|
214
|
+
return;
|
|
215
|
+
const prefetchQueue = [];
|
|
216
|
+
// Start initial prefetch
|
|
217
|
+
let prefetchPosition = position;
|
|
218
|
+
for (let i = 0; i < Math.min(prefetch, linksToProcess.length); i++) {
|
|
219
|
+
const link = linksToProcess[i];
|
|
220
|
+
prefetchQueue.push({
|
|
221
|
+
promise: store.get(link.hash),
|
|
222
|
+
link,
|
|
223
|
+
position: prefetchPosition,
|
|
224
|
+
});
|
|
225
|
+
prefetchPosition += link.size ?? 0;
|
|
226
|
+
}
|
|
227
|
+
// Process links
|
|
228
|
+
let nextPrefetchIdx = prefetch;
|
|
229
|
+
for (const link of linksToProcess) {
|
|
230
|
+
const chunkKey = link.key;
|
|
231
|
+
if (!chunkKey) {
|
|
232
|
+
throw new Error(`Missing decryption key for chunk: ${toHex(link.hash)}`);
|
|
233
|
+
}
|
|
234
|
+
// Get data from prefetch queue (should be first item)
|
|
235
|
+
const entry = prefetchQueue.shift();
|
|
236
|
+
if (!entry) {
|
|
237
|
+
throw new Error('Prefetch queue empty unexpectedly');
|
|
238
|
+
}
|
|
239
|
+
const encryptedChild = await entry.promise;
|
|
240
|
+
if (!encryptedChild) {
|
|
241
|
+
throw new Error(`Missing chunk: ${toHex(link.hash)}`);
|
|
242
|
+
}
|
|
243
|
+
// Start prefetching next chunk
|
|
244
|
+
if (nextPrefetchIdx < linksToProcess.length) {
|
|
245
|
+
const nextLink = linksToProcess[nextPrefetchIdx];
|
|
246
|
+
prefetchQueue.push({
|
|
247
|
+
promise: store.get(nextLink.hash),
|
|
248
|
+
link: nextLink,
|
|
249
|
+
position: prefetchPosition,
|
|
250
|
+
});
|
|
251
|
+
prefetchPosition += nextLink.size ?? 0;
|
|
252
|
+
nextPrefetchIdx++;
|
|
253
|
+
}
|
|
254
|
+
const decrypted = await decryptChk(encryptedChild, chunkKey);
|
|
255
|
+
if (link.type !== LinkType.Blob) {
|
|
256
|
+
// Intermediate tree node - decode and recurse with prefetch
|
|
257
|
+
const childNode = decodeTreeNode(decrypted);
|
|
258
|
+
const childOffset = Math.max(0, offset - entry.position);
|
|
259
|
+
yield* streamEncryptedChunksWithOffset(store, childNode, childOffset, prefetch);
|
|
260
|
+
position = entry.position + (link.size ?? 0);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
// Leaf chunk - raw blob
|
|
264
|
+
const chunkStart = entry.position;
|
|
265
|
+
const chunkEnd = entry.position + decrypted.length;
|
|
266
|
+
position = chunkEnd;
|
|
267
|
+
if (chunkEnd <= offset) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (chunkStart >= offset) {
|
|
271
|
+
yield decrypted;
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
const sliceStart = offset - chunkStart;
|
|
275
|
+
yield decrypted.slice(sliceStart);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Read a range of bytes from an encrypted file
|
|
282
|
+
*/
|
|
283
|
+
export async function readFileEncryptedRange(store, hash, key, start, end) {
|
|
284
|
+
const encryptedData = await store.get(hash);
|
|
285
|
+
if (!encryptedData)
|
|
286
|
+
return null;
|
|
287
|
+
const decrypted = await decryptChk(encryptedData, key);
|
|
288
|
+
const node = tryDecodeTreeNode(decrypted);
|
|
289
|
+
if (!node) {
|
|
290
|
+
// Single blob
|
|
291
|
+
if (start >= decrypted.length)
|
|
292
|
+
return new Uint8Array(0);
|
|
293
|
+
const actualEnd = end !== undefined ? Math.min(end, decrypted.length) : decrypted.length;
|
|
294
|
+
return decrypted.slice(start, actualEnd);
|
|
295
|
+
}
|
|
296
|
+
return readEncryptedRangeFromNode(store, node, start, end);
|
|
297
|
+
}
|
|
298
|
+
async function readEncryptedRangeFromNode(store, node, start, end) {
|
|
299
|
+
const parts = [];
|
|
300
|
+
let position = 0;
|
|
301
|
+
let bytesCollected = 0;
|
|
302
|
+
const maxBytes = end !== undefined ? end - start : Infinity;
|
|
303
|
+
for (const link of node.links) {
|
|
304
|
+
if (bytesCollected >= maxBytes)
|
|
305
|
+
break;
|
|
306
|
+
const chunkKey = link.key;
|
|
307
|
+
if (!chunkKey) {
|
|
308
|
+
throw new Error(`Missing decryption key for chunk: ${toHex(link.hash)}`);
|
|
309
|
+
}
|
|
310
|
+
const linkSize = link.size ?? 0;
|
|
311
|
+
// Skip chunks entirely before start
|
|
312
|
+
if (linkSize > 0 && position + linkSize <= start) {
|
|
313
|
+
position += linkSize;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
const encryptedChild = await store.get(link.hash);
|
|
317
|
+
if (!encryptedChild) {
|
|
318
|
+
throw new Error(`Missing chunk: ${toHex(link.hash)}`);
|
|
319
|
+
}
|
|
320
|
+
const decrypted = await decryptChk(encryptedChild, chunkKey);
|
|
321
|
+
if (link.type !== LinkType.Blob) {
|
|
322
|
+
// Intermediate tree node - decode and recurse
|
|
323
|
+
const childNode = decodeTreeNode(decrypted);
|
|
324
|
+
const childStart = Math.max(0, start - position);
|
|
325
|
+
const childEnd = end !== undefined ? end - position : undefined;
|
|
326
|
+
const childData = await readEncryptedRangeFromNode(store, childNode, childStart, childEnd);
|
|
327
|
+
if (childData.length > 0) {
|
|
328
|
+
const take = Math.min(childData.length, maxBytes - bytesCollected);
|
|
329
|
+
parts.push(childData.slice(0, take));
|
|
330
|
+
bytesCollected += take;
|
|
331
|
+
}
|
|
332
|
+
position += linkSize;
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
// Leaf chunk - raw blob
|
|
336
|
+
const chunkStart = position;
|
|
337
|
+
const chunkEnd = position + decrypted.length;
|
|
338
|
+
position = chunkEnd;
|
|
339
|
+
if (chunkEnd <= start) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const sliceStart = Math.max(0, start - chunkStart);
|
|
343
|
+
const sliceEnd = end !== undefined
|
|
344
|
+
? Math.min(decrypted.length, end - chunkStart)
|
|
345
|
+
: decrypted.length;
|
|
346
|
+
if (sliceStart < sliceEnd) {
|
|
347
|
+
const take = Math.min(sliceEnd - sliceStart, maxBytes - bytesCollected);
|
|
348
|
+
parts.push(decrypted.slice(sliceStart, sliceStart + take));
|
|
349
|
+
bytesCollected += take;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// Concatenate parts
|
|
354
|
+
const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
|
|
355
|
+
const result = new Uint8Array(totalLength);
|
|
356
|
+
let concatOffset = 0;
|
|
357
|
+
for (const part of parts) {
|
|
358
|
+
result.set(part, concatOffset);
|
|
359
|
+
concatOffset += part.length;
|
|
360
|
+
}
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Store a directory with CHK encryption
|
|
365
|
+
*
|
|
366
|
+
* The directory node itself is encrypted. Child entries already have their own keys.
|
|
367
|
+
* Large directories are chunked by bytes like files using putFileEncrypted.
|
|
368
|
+
*
|
|
369
|
+
* @param config - Tree configuration
|
|
370
|
+
* @param entries - Directory entries (with keys for encrypted children)
|
|
371
|
+
* @returns Hash of encrypted directory and the encryption key
|
|
372
|
+
*/
|
|
373
|
+
export async function putDirectoryEncrypted(config, entries) {
|
|
374
|
+
const { store, chunkSize } = config;
|
|
375
|
+
const sorted = [...entries].sort((a, b) => a.name.localeCompare(b.name));
|
|
376
|
+
const links = sorted.map(e => ({
|
|
377
|
+
hash: e.hash,
|
|
378
|
+
name: e.name,
|
|
379
|
+
size: e.size,
|
|
380
|
+
key: e.key,
|
|
381
|
+
type: e.type,
|
|
382
|
+
meta: e.meta,
|
|
383
|
+
}));
|
|
384
|
+
const totalSize = links.reduce((sum, l) => sum + l.size, 0);
|
|
385
|
+
const node = {
|
|
386
|
+
type: LinkType.Dir,
|
|
387
|
+
links,
|
|
388
|
+
};
|
|
389
|
+
const { data } = await encodeAndHash(node);
|
|
390
|
+
// Small directory - encrypt and store directly
|
|
391
|
+
if (data.length <= chunkSize) {
|
|
392
|
+
const { ciphertext, key } = await encryptChk(data);
|
|
393
|
+
const hash = await sha256(ciphertext);
|
|
394
|
+
await store.put(hash, ciphertext);
|
|
395
|
+
return { hash, size: totalSize, key };
|
|
396
|
+
}
|
|
397
|
+
// Large directory - reuse putFileEncrypted for chunking
|
|
398
|
+
return putFileEncrypted(config, data);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* List directory entries from an encrypted directory
|
|
402
|
+
*
|
|
403
|
+
* Handles both small directories (single node) and large directories
|
|
404
|
+
* (chunked by bytes like files).
|
|
405
|
+
*
|
|
406
|
+
* @param store - Storage backend
|
|
407
|
+
* @param hash - Hash of encrypted directory
|
|
408
|
+
* @param key - CHK decryption key
|
|
409
|
+
* @returns Directory entries with their encryption keys
|
|
410
|
+
*/
|
|
411
|
+
export async function listDirectoryEncrypted(store, hash, key) {
|
|
412
|
+
const node = await getEncryptedDirectoryNode(store, hash, key);
|
|
413
|
+
if (!node)
|
|
414
|
+
return [];
|
|
415
|
+
// Extract directory entries from the node
|
|
416
|
+
const entries = [];
|
|
417
|
+
for (const link of node.links) {
|
|
418
|
+
if (link.name) {
|
|
419
|
+
entries.push({
|
|
420
|
+
name: link.name,
|
|
421
|
+
hash: link.hash,
|
|
422
|
+
size: link.size,
|
|
423
|
+
key: link.key,
|
|
424
|
+
type: link.type,
|
|
425
|
+
meta: link.meta,
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return entries;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Get a tree node from encrypted storage
|
|
433
|
+
*
|
|
434
|
+
* @param store - Storage backend
|
|
435
|
+
* @param hash - Hash of encrypted node
|
|
436
|
+
* @param key - CHK decryption key
|
|
437
|
+
* @returns Decrypted tree node
|
|
438
|
+
*/
|
|
439
|
+
export async function getTreeNodeEncrypted(store, hash, key) {
|
|
440
|
+
const encryptedData = await store.get(hash);
|
|
441
|
+
if (!encryptedData)
|
|
442
|
+
return null;
|
|
443
|
+
const decrypted = await decryptChk(encryptedData, key);
|
|
444
|
+
return tryDecodeTreeNode(decrypted);
|
|
445
|
+
}
|
|
446
|
+
//# sourceMappingURL=encrypted.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypted.js","sourceRoot":"","sources":["../src/encrypted.ts"],"names":[],"mappings":"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"}
|
package/dist/hash.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hashing utilities using Web Crypto API (browser-only)
|
|
3
|
+
*/
|
|
4
|
+
import { Hash } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Compute SHA256 hash of data
|
|
7
|
+
* Uses Web Crypto API - browser environments only
|
|
8
|
+
*/
|
|
9
|
+
export declare function sha256(data: Uint8Array): Promise<Hash>;
|
|
10
|
+
/**
|
|
11
|
+
* Verify that data matches expected hash
|
|
12
|
+
*/
|
|
13
|
+
export declare function verify(hash: Hash, data: Uint8Array): Promise<boolean>;
|
|
14
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC;;;GAGG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5D;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E"}
|
package/dist/hash.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hashing utilities using Web Crypto API (browser-only)
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Compute SHA256 hash of data
|
|
6
|
+
* Uses Web Crypto API - browser environments only
|
|
7
|
+
*/
|
|
8
|
+
export async function sha256(data) {
|
|
9
|
+
const buffer = new ArrayBuffer(data.length);
|
|
10
|
+
new Uint8Array(buffer).set(data);
|
|
11
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
|
|
12
|
+
return new Uint8Array(hashBuffer);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Verify that data matches expected hash
|
|
16
|
+
*/
|
|
17
|
+
export async function verify(hash, data) {
|
|
18
|
+
const computed = await sha256(data);
|
|
19
|
+
if (computed.length !== hash.length)
|
|
20
|
+
return false;
|
|
21
|
+
for (let i = 0; i < computed.length; i++) {
|
|
22
|
+
if (computed[i] !== hash[i])
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=hash.js.map
|
package/dist/hash.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAgB;IAC3C,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACjE,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAU,EAAE,IAAgB;IACvD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|