@storacha/encrypt-upload-client 0.0.39 → 1.0.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.
Files changed (51) hide show
  1. package/dist/core/client.d.ts +8 -12
  2. package/dist/core/client.d.ts.map +1 -1
  3. package/dist/core/client.js +12 -21
  4. package/dist/core/metadata/encrypted-metadata.d.ts +8 -0
  5. package/dist/core/metadata/encrypted-metadata.d.ts.map +1 -0
  6. package/dist/core/metadata/encrypted-metadata.js +69 -0
  7. package/dist/core/metadata/kms-metadata.d.ts +36 -0
  8. package/dist/core/metadata/kms-metadata.d.ts.map +1 -0
  9. package/dist/core/metadata/kms-metadata.js +156 -0
  10. package/dist/core/{encrypted-metadata.d.ts → metadata/lit-metadata.d.ts} +11 -11
  11. package/dist/core/metadata/lit-metadata.d.ts.map +1 -0
  12. package/dist/core/{encrypted-metadata.js → metadata/lit-metadata.js} +32 -42
  13. package/dist/crypto/adapters/kms-crypto-adapter.d.ts +148 -0
  14. package/dist/crypto/adapters/kms-crypto-adapter.d.ts.map +1 -0
  15. package/dist/crypto/adapters/kms-crypto-adapter.js +321 -0
  16. package/dist/crypto/adapters/lit-crypto-adapter.d.ts +96 -0
  17. package/dist/crypto/adapters/lit-crypto-adapter.d.ts.map +1 -0
  18. package/dist/crypto/adapters/lit-crypto-adapter.js +210 -0
  19. package/dist/crypto/factories.browser.d.ts +20 -0
  20. package/dist/crypto/factories.browser.d.ts.map +1 -0
  21. package/dist/crypto/factories.browser.js +28 -0
  22. package/dist/crypto/factories.node.d.ts +26 -0
  23. package/dist/crypto/factories.node.d.ts.map +1 -0
  24. package/dist/crypto/factories.node.js +38 -0
  25. package/dist/crypto/index.d.ts +5 -0
  26. package/dist/crypto/index.d.ts.map +1 -0
  27. package/dist/crypto/index.js +7 -0
  28. package/dist/crypto/symmetric/generic-aes-ctr-streaming-crypto.d.ts +76 -0
  29. package/dist/crypto/symmetric/generic-aes-ctr-streaming-crypto.d.ts.map +1 -0
  30. package/dist/crypto/symmetric/generic-aes-ctr-streaming-crypto.js +177 -0
  31. package/dist/crypto/symmetric/node-aes-cbc-crypto.d.ts +43 -0
  32. package/dist/crypto/symmetric/node-aes-cbc-crypto.d.ts.map +1 -0
  33. package/dist/crypto/symmetric/node-aes-cbc-crypto.js +110 -0
  34. package/dist/handlers/decrypt-handler.d.ts +9 -4
  35. package/dist/handlers/decrypt-handler.d.ts.map +1 -1
  36. package/dist/handlers/decrypt-handler.js +62 -93
  37. package/dist/handlers/encrypt-handler.d.ts +1 -1
  38. package/dist/handlers/encrypt-handler.d.ts.map +1 -1
  39. package/dist/handlers/encrypt-handler.js +31 -41
  40. package/dist/protocols/lit.d.ts +1 -3
  41. package/dist/protocols/lit.d.ts.map +1 -1
  42. package/dist/types.d.ts +135 -20
  43. package/dist/types.d.ts.map +1 -1
  44. package/package.json +27 -18
  45. package/dist/core/encrypted-metadata.d.ts.map +0 -1
  46. package/dist/crypto-adapters/browser-crypto-adapter.d.ts +0 -42
  47. package/dist/crypto-adapters/browser-crypto-adapter.d.ts.map +0 -1
  48. package/dist/crypto-adapters/browser-crypto-adapter.js +0 -109
  49. package/dist/crypto-adapters/node-crypto-adapter.d.ts +0 -17
  50. package/dist/crypto-adapters/node-crypto-adapter.d.ts.map +0 -1
  51. package/dist/crypto-adapters/node-crypto-adapter.js +0 -66
@@ -0,0 +1,110 @@
1
+ import { randomBytes, createCipheriv, createDecipheriv } from 'crypto';
2
+ import * as Type from '../../types.js';
3
+ const ENCRYPTION_ALGORITHM = 'aes-256-cbc';
4
+ const KEY_LENGTH = 256; // bits
5
+ const IV_LENGTH = 16; // bytes (128 bits, used as initialization vector)
6
+ /**
7
+ * NodeAesCbcCrypto implements AES-CBC symmetric encryption for Node.js environments.
8
+ * It uses AES-CBC mode for encryption via the Node.js crypto module.
9
+ * If you already encrypted a file with this class, you still need to use this class to decrypt it.
10
+ *
11
+ * @deprecated Use GenericAesCtrStreamingCrypto instead for new uploads
12
+ * @class
13
+ * @implements {Type.SymmetricCrypto}
14
+ */
15
+ export class NodeAesCbcCrypto {
16
+ /** @param {Type.BlobLike} data */
17
+ async encryptStream(data) {
18
+ const symmetricKey = randomBytes(KEY_LENGTH / 8); // KEY_LENGTH bits for AES
19
+ const initializationVector = randomBytes(IV_LENGTH); // IV_LENGTH bytes for AES
20
+ const cipher = createCipheriv(ENCRYPTION_ALGORITHM, symmetricKey, initializationVector);
21
+ const encryptStream = new TransformStream({
22
+ transform: async (chunk, controller) => {
23
+ const encryptedChunk = cipher.update(chunk);
24
+ if (encryptedChunk.length) {
25
+ controller.enqueue(encryptedChunk);
26
+ }
27
+ },
28
+ flush: (controller) => {
29
+ const final = cipher.final();
30
+ if (final.length) {
31
+ controller.enqueue(final);
32
+ }
33
+ },
34
+ });
35
+ return Promise.resolve({
36
+ key: symmetricKey,
37
+ iv: initializationVector,
38
+ encryptedStream: data.stream().pipeThrough(encryptStream),
39
+ });
40
+ }
41
+ /**
42
+ * @param {ReadableStream} encryptedData
43
+ * @param {Uint8Array} key
44
+ * @param {Uint8Array} iv
45
+ */
46
+ async decryptStream(encryptedData, key, iv) {
47
+ const decipher = createDecipheriv(ENCRYPTION_ALGORITHM, key, iv);
48
+ const decryptor = new TransformStream({
49
+ async transform(chunk, controller) {
50
+ try {
51
+ const decryptedChunk = decipher.update(chunk);
52
+ if (decryptedChunk.length > 0) {
53
+ controller.enqueue(decryptedChunk);
54
+ }
55
+ }
56
+ catch (err) {
57
+ controller.error(err);
58
+ }
59
+ },
60
+ flush(controller) {
61
+ try {
62
+ const finalChunk = decipher.final();
63
+ if (finalChunk.length > 0) {
64
+ controller.enqueue(finalChunk);
65
+ }
66
+ controller.terminate();
67
+ }
68
+ catch (err) {
69
+ controller.error(err);
70
+ }
71
+ },
72
+ });
73
+ return Promise.resolve(encryptedData.pipeThrough(decryptor));
74
+ }
75
+ /**
76
+ * Combine key and IV into a single array for AES-CBC
77
+ *
78
+ * @param {Uint8Array} key - The AES key (KEY_LENGTH/8 bytes)
79
+ * @param {Uint8Array} iv - The AES-CBC IV (IV_LENGTH bytes)
80
+ * @returns {Uint8Array} Combined key and IV (KEY_LENGTH/8 + IV_LENGTH bytes)
81
+ */
82
+ combineKeyAndIV(key, iv) {
83
+ const keyBytes = KEY_LENGTH / 8;
84
+ if (key.length !== keyBytes) {
85
+ throw new Error(`AES-${KEY_LENGTH} key must be ${keyBytes} bytes, got ${key.length}`);
86
+ }
87
+ if (iv.length !== IV_LENGTH) {
88
+ throw new Error(`AES-CBC IV must be ${IV_LENGTH} bytes, got ${iv.length}`);
89
+ }
90
+ return new Uint8Array([...key, ...iv]);
91
+ }
92
+ /**
93
+ * Split combined key and IV for AES-CBC
94
+ *
95
+ * @param {Uint8Array} combined - Combined key and IV (KEY_LENGTH/8 + IV_LENGTH bytes)
96
+ * @returns {{ key: Uint8Array, iv: Uint8Array }} Separated key and IV
97
+ */
98
+ splitKeyAndIV(combined) {
99
+ const keyBytes = KEY_LENGTH / 8;
100
+ const expectedLength = keyBytes + IV_LENGTH;
101
+ if (combined.length !== expectedLength) {
102
+ throw new Error(`AES-${KEY_LENGTH}-CBC combined key+IV must be ${expectedLength} bytes, got ${combined.length}`);
103
+ }
104
+ return {
105
+ key: combined.subarray(0, keyBytes),
106
+ iv: combined.subarray(keyBytes, keyBytes + IV_LENGTH),
107
+ };
108
+ }
109
+ }
110
+ //# sourceMappingURL=node-aes-cbc-crypto.js.map
@@ -1,10 +1,15 @@
1
1
  /**
2
+ * Decrypt file content using the decrypted symmetric key and IV.
3
+ *
2
4
  * @param {Type.CryptoAdapter} cryptoAdapter - The crypto adapter responsible for performing
3
5
  * encryption and decryption operations.
4
- * @param {string} combinedKey
5
- * @param {Uint8Array} content
6
+ * @param {Uint8Array} key - The symmetric key
7
+ * @param {Uint8Array} iv - The initialization vector
8
+ * @param {Uint8Array} content - The encrypted file content
9
+ * @returns {Promise<ReadableStream>} The decrypted file stream
6
10
  */
7
- export function decryptFileWithKey(cryptoAdapter: Type.CryptoAdapter, combinedKey: string, content: Uint8Array): Promise<ReadableStream<any>>;
8
- export function retrieveAndDecrypt(storachaClient: import("@storacha/client").Client, litClient: import("@lit-protocol/lit-node-client").LitNodeClient, cryptoAdapter: Type.CryptoAdapter, gatewayURL: URL, signer: Type.LitWalletSigner | Type.LitPkpSigner, cid: Type.AnyLink, delegationCAR: Uint8Array): Promise<ReadableStream<any>>;
11
+ export function decryptFileWithKey(cryptoAdapter: Type.CryptoAdapter, key: Uint8Array, iv: Uint8Array, content: Uint8Array): Promise<ReadableStream>;
12
+ export function retrieveAndDecrypt(storachaClient: import("@storacha/client").Client, cryptoAdapter: Type.CryptoAdapter, gatewayURL: URL, cid: Type.AnyLink, delegationCAR: Uint8Array, decryptionOptions: Type.DecryptionOptions): Promise<ReadableStream>;
13
+ export function getCarFileFromPublicGateway(gatewayURL: URL, cid: string): Promise<Uint8Array>;
9
14
  import * as Type from '../types.js';
10
15
  //# sourceMappingURL=decrypt-handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decrypt-handler.d.ts","sourceRoot":"","sources":["../../src/handlers/decrypt-handler.js"],"names":[],"mappings":"AAuGA;;;;;GAKG;AACH,kDALW,IAAI,CAAC,aAAa,eAElB,MAAM,WACN,UAAU,gCAuBpB;AA3GM,mDATI,OAAO,kBAAkB,EAAE,MAAM,aACjC,OAAO,+BAA+B,EAAE,aAAa,iBACrD,IAAI,CAAC,aAAa,cAElB,GAAG,UACH,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,YAAY,OACxC,IAAI,CAAC,OAAO,iBACZ,UAAU,gCAgFpB;sBA9FqB,aAAa"}
1
+ {"version":3,"file":"decrypt-handler.d.ts","sourceRoot":"","sources":["../../src/handlers/decrypt-handler.js"],"names":[],"mappings":"AA4DA;;;;;;;;;GASG;AACH,kDAPW,IAAI,CAAC,aAAa,OAElB,UAAU,MACV,UAAU,WACV,UAAU,GACR,OAAO,CAAC,cAAc,CAAC,CAanC;AA9DM,mDATI,OAAO,kBAAkB,EAAE,MAAM,iBACjC,IAAI,CAAC,aAAa,cAElB,GAAG,OACH,IAAI,CAAC,OAAO,iBACZ,UAAU,qBACV,IAAI,CAAC,iBAAiB,GACpB,OAAO,CAAC,cAAc,CAAC,CAyCnC;AAoCM,wDAJI,GAAG,OACH,MAAM,GACJ,OAAO,CAAC,UAAU,CAAC,CA+B/B;sBAtHqB,aAAa"}
@@ -1,144 +1,113 @@
1
1
  import { CID } from 'multiformats';
2
- import { CarIndexer } from '@ipld/car';
2
+ import { CarIndexer, CarReader } from '@ipld/car';
3
3
  import { exporter } from 'ipfs-unixfs-exporter';
4
4
  import { MemoryBlockstore } from 'blockstore-core';
5
- import { base64 } from 'multiformats/bases/base64';
6
- import * as Lit from '../protocols/lit.js';
7
5
  import * as Type from '../types.js';
8
- import * as EncryptedMetadata from '../core/encrypted-metadata.js';
9
- import { createDecryptWrappedInvocation } from '../utils.js';
10
6
  /**
11
- * Retrieve and decrypt a file from the IPFS gateway.
7
+ * Retrieve and decrypt a file from the IPFS gateway using any supported encryption strategy.
12
8
  *
13
9
  * @param {import('@storacha/client').Client} storachaClient - The Storacha client
14
- * @param {import('@lit-protocol/lit-node-client').LitNodeClient} litClient - The Lit client
15
10
  * @param {Type.CryptoAdapter} cryptoAdapter - The crypto adapter responsible for performing
16
11
  * encryption and decryption operations.
17
12
  * @param {URL} gatewayURL - The IPFS gateway URL
18
- * @param {Type.LitWalletSigner | Type.LitPkpSigner} signer - The wallet or PKP key signer to decrypt the file
19
13
  * @param {Type.AnyLink} cid - The link to the file to retrieve
20
- * @param {Uint8Array} delegationCAR - The delegation that gives permission to decrypt the file
14
+ * @param {Uint8Array} delegationCAR - The delegation that gives permission to decrypt (required for both strategies)
15
+ * @param {Type.DecryptionOptions} decryptionOptions - User-provided decryption options
16
+ * @returns {Promise<ReadableStream>} The decrypted file stream
21
17
  */
22
- export const retrieveAndDecrypt = async (storachaClient, litClient, cryptoAdapter, gatewayURL, signer, cid, delegationCAR) => {
23
- const encryptedMetadataCar = await getCarFileFromGateway(gatewayURL, cid.toString());
24
- const { encryptedDataCID, identityBoundCiphertext, plaintextKeyHash, accessControlConditions, } = extractEncryptedMetadata(encryptedMetadataCar);
25
- const spaceDID = /** @type {`did:key:${string}`} */ (accessControlConditions[0].parameters[1]);
26
- const encryptedData = await getEncryptedDataFromCar(encryptedMetadataCar, encryptedDataCID);
27
- if (!signer) {
28
- throw new Error('Signer is required');
29
- }
30
- /**
31
- * TODO: check if the wallet has capacity credits, if not get it
32
- */
33
- const acc =
34
- /** @type import('@lit-protocol/types').AccessControlConditions */ (
35
- /** @type {unknown} */ (accessControlConditions));
36
- const expiration = new Date(Date.now() + 1000 * 60 * 5).toISOString(); // 5 min
37
- // TODO: store the session signature (https://developer.litprotocol.com/intro/first-request/generating-session-sigs#nodejs)
38
- let sessionSigs;
39
- if ('wallet' in signer) {
40
- sessionSigs = await Lit.getSessionSigs(litClient, {
41
- wallet: signer.wallet,
42
- dataToEncryptHash: plaintextKeyHash,
43
- expiration,
44
- accessControlConditions: acc,
45
- });
46
- }
47
- else {
48
- sessionSigs = await Lit.getPkpSessionSigs(litClient, {
49
- pkpPublicKey: signer.pkpPublicKey,
50
- authMethod: signer.authMethod,
51
- dataToEncryptHash: plaintextKeyHash,
52
- expiration,
53
- accessControlConditions: acc,
54
- });
55
- }
56
- const wrappedInvocationJSON = await createDecryptWrappedInvocation({
18
+ export const retrieveAndDecrypt = async (storachaClient, cryptoAdapter, gatewayURL, cid, delegationCAR, decryptionOptions) => {
19
+ // Step 1: Get the encrypted metadata from the public gateway
20
+ const encryptedMetadataCar = await getCarFileFromPublicGateway(gatewayURL, cid.toString());
21
+ // Step 2: Extract encrypted metadata from the CAR file
22
+ const metadata = cryptoAdapter.extractEncryptedMetadata(encryptedMetadataCar);
23
+ // Step 3: Get the encrypted data from the CAR file
24
+ const encryptedData = await getEncryptedDataFromCar(encryptedMetadataCar, metadata.encryptedDataCID);
25
+ // Step 4: Decrypt the encrypted symmetric key
26
+ const encryptedSymmetricKey = cryptoAdapter.getEncryptedKey(metadata);
27
+ const { key, iv } = await cryptoAdapter.decryptSymmetricKey(encryptedSymmetricKey, {
28
+ decryptionOptions,
29
+ metadata,
57
30
  delegationCAR,
58
- spaceDID,
59
31
  resourceCID: cid,
60
32
  issuer: storachaClient.agent.issuer,
61
33
  audience: storachaClient.defaultProvider(),
62
- expiration: new Date(Date.now() + 1000 * 60 * 10).getTime(), // 10 min
63
34
  });
64
- const decryptKey = await Lit.executeUcanValidationAction(litClient, {
65
- sessionSigs,
66
- spaceDID,
67
- identityBoundCiphertext,
68
- plaintextKeyHash,
69
- accessControlConditions,
70
- wrappedInvocationJSON,
71
- });
72
- return decryptFileWithKey(cryptoAdapter, decryptKey, encryptedData);
35
+ // Step 5: Decrypt the encrypted file content using the decrypted symmetric key and IV
36
+ return decryptFileWithKey(cryptoAdapter, key, iv, encryptedData);
73
37
  };
74
38
  /**
39
+ * Decrypt file content using the decrypted symmetric key and IV.
40
+ *
75
41
  * @param {Type.CryptoAdapter} cryptoAdapter - The crypto adapter responsible for performing
76
42
  * encryption and decryption operations.
77
- * @param {string} combinedKey
78
- * @param {Uint8Array} content
43
+ * @param {Uint8Array} key - The symmetric key
44
+ * @param {Uint8Array} iv - The initialization vector
45
+ * @param {Uint8Array} content - The encrypted file content
46
+ * @returns {Promise<ReadableStream>} The decrypted file stream
79
47
  */
80
- export function decryptFileWithKey(cryptoAdapter, combinedKey, content) {
81
- // Split the decrypted data back into key and initializationVector
82
- const decryptedKeyData = base64.decode(combinedKey);
83
- const symmetricKey = decryptedKeyData.subarray(0, 32);
84
- const initializationVector = decryptedKeyData.subarray(32);
85
- // Create a ReadableStream from the Uint8Array
48
+ export function decryptFileWithKey(cryptoAdapter, key, iv, content) {
86
49
  const contentStream = new ReadableStream({
87
50
  start(controller) {
88
51
  controller.enqueue(content);
89
52
  controller.close();
90
53
  },
91
54
  });
92
- const decryptedStream = cryptoAdapter.decryptStream(contentStream, symmetricKey, initializationVector);
55
+ const decryptedStream = cryptoAdapter.decryptStream(contentStream, key, iv);
93
56
  return decryptedStream;
94
57
  }
95
58
  /**
59
+ * Fetch a CAR file from the public IPFS gateway with root CID verification.
96
60
  *
97
- * @param {URL} gatewayURL
98
- * @param {string} cid
61
+ * SECURITY: This function provides metadata integrity protection (P0.2).
62
+ * Verifies the returned CAR matches the requested CID to prevent metadata tampering.
63
+ * Content integrity (P2.2) is handled by existing IPFS tools in getEncryptedDataFromCar.
64
+ *
65
+ * @param {URL} gatewayURL - The IPFS gateway URL
66
+ * @param {string} cid - The CID to fetch
67
+ * @returns {Promise<Uint8Array>} The verified CAR file bytes
99
68
  */
100
- const getCarFileFromGateway = async (gatewayURL, cid) => {
69
+ export const getCarFileFromPublicGateway = async (gatewayURL, cid) => {
101
70
  const url = new URL(`/ipfs/${cid}?format=car`, gatewayURL);
102
71
  const response = await fetch(url);
103
72
  if (!response.ok) {
104
73
  throw new Error(`Failed to fetch: ${response.status} ${response.statusText}`);
105
74
  }
106
75
  const car = new Uint8Array(await response.arrayBuffer());
107
- return car;
108
- };
109
- /**
110
- *
111
- * @param {Uint8Array} car
112
- */
113
- const extractEncryptedMetadata = (car) => {
114
- const encryptedContentResult = EncryptedMetadata.extract(car);
115
- if (encryptedContentResult.error) {
116
- throw encryptedContentResult.error;
76
+ // SECURITY: Verify the CAR's root CID matches what we requested
77
+ const reader = await CarReader.fromBytes(car);
78
+ const roots = await reader.getRoots();
79
+ const expectedCID = CID.parse(cid);
80
+ if (roots.length !== 1) {
81
+ throw new Error(`CAR file must have exactly one root CID, found ${roots.length}`);
82
+ }
83
+ if (!roots[0].equals(expectedCID)) {
84
+ throw new Error(`CID verification failed: expected ${expectedCID} but CAR contains ${roots[0]}`);
117
85
  }
118
- let encryptedContent = encryptedContentResult.ok.toJSON();
119
- return encryptedContent;
86
+ return car;
120
87
  };
121
88
  /**
89
+ * Extract encrypted data from a CAR file.
122
90
  *
123
- * @param {Uint8Array} car
124
- * @param {string} encryptedDataCID
91
+ * @param {Uint8Array} car - The CAR file bytes
92
+ * @param {string} encryptedDataCID - The CID of the encrypted data
93
+ * @returns {Promise<Uint8Array>} The encrypted data bytes
125
94
  */
126
95
  const getEncryptedDataFromCar = async (car, encryptedDataCID) => {
127
- // NOTE: convert CAR to a block store
96
+ // Step 1: Index the CAR file for efficient block lookup
128
97
  const iterable = await CarIndexer.fromBytes(car);
129
- const blockstore = new MemoryBlockstore();
98
+ const blockIndex = new Map();
130
99
  for await (const { cid, blockLength, blockOffset } of iterable) {
131
- const blockBytes = car.slice(blockOffset, blockOffset + blockLength);
132
- await blockstore.put(cid, blockBytes);
100
+ blockIndex.set(cid.toString(), { blockOffset, blockLength });
133
101
  }
134
- // NOTE: get the encrypted Data from the CAR file
102
+ // Step 2: Use the index to extract the encrypted data block bytes as needed
103
+ const { blockOffset, blockLength } = blockIndex.get(encryptedDataCID);
104
+ const blockBytes = car.subarray(blockOffset, blockOffset + blockLength);
105
+ // Step 3: Put the block in a blockstore for exporter compatibility
106
+ const blockstore = new MemoryBlockstore();
107
+ await blockstore.put(CID.parse(encryptedDataCID), blockBytes);
108
+ // Step 4: Get the encrypted data from the CAR file
135
109
  const encryptedDataEntry = await exporter(CID.parse(encryptedDataCID), blockstore);
136
- const encryptedDataBytes = new Uint8Array(Number(encryptedDataEntry.size));
137
- let offset = 0;
138
- for await (const chunk of encryptedDataEntry.content()) {
139
- encryptedDataBytes.set(chunk, offset);
140
- offset += chunk.length;
141
- }
142
- return encryptedDataBytes;
110
+ // Step 5: Return the async iterable (stream of chunks)
111
+ return encryptedDataEntry.content(); // async iterable of Uint8Array
143
112
  };
144
113
  //# sourceMappingURL=decrypt-handler.js.map
@@ -1,3 +1,3 @@
1
- export function encryptAndUpload(storachaClient: import("@storacha/client").Client, litClient: import("@lit-protocol/lit-node-client").LitNodeClient, cryptoAdapter: Type.CryptoAdapter, file: Type.BlobLike): Promise<Type.AnyLink>;
1
+ export function encryptAndUpload(storachaClient: import("@storacha/client").Client, cryptoAdapter: Type.CryptoAdapter, file: Type.BlobLike, encryptionConfig: Type.EncryptionConfig, uploadOptions?: Type.UploadOptions): Promise<Type.AnyLink>;
2
2
  import * as Type from '../types.js';
3
3
  //# sourceMappingURL=encrypt-handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"encrypt-handler.d.ts","sourceRoot":"","sources":["../../src/handlers/encrypt-handler.js"],"names":[],"mappings":"AAkBO,iDAPI,OAAO,kBAAkB,EAAE,MAAM,aACjC,OAAO,+BAA+B,EAAE,aAAa,iBACrD,IAAI,CAAC,aAAa,QAElB,IAAI,CAAC,QAAQ,GACX,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CA4BjC;sBAxCqB,aAAa"}
1
+ {"version":3,"file":"encrypt-handler.d.ts","sourceRoot":"","sources":["../../src/handlers/encrypt-handler.js"],"names":[],"mappings":"AAgBO,iDARI,OAAO,kBAAkB,EAAE,MAAM,iBACjC,IAAI,CAAC,aAAa,QAElB,IAAI,CAAC,QAAQ,oBACb,IAAI,CAAC,gBAAgB,kBACrB,IAAI,CAAC,aAAa,GAChB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CA6BjC;sBAxCqB,aAAa"}
@@ -1,42 +1,39 @@
1
1
  import { CARWriterStream } from 'carstream';
2
- import { base64 } from 'multiformats/bases/base64';
3
2
  import { createFileEncoderStream } from '@storacha/upload-client/unixfs';
4
3
  import * as Type from '../types.js';
5
- import * as Lit from '../protocols/lit.js';
6
- import * as EncryptedMetadata from '../core/encrypted-metadata.js';
7
4
  /**
8
5
  * Encrypt and upload a file to the Storacha network
9
6
  *
10
7
  * @param {import('@storacha/client').Client} storachaClient - The Storacha client
11
- * @param {import('@lit-protocol/lit-node-client').LitNodeClient} litClient - The Lit client
12
8
  * @param {Type.CryptoAdapter} cryptoAdapter - The crypto adapter responsible for performing
13
9
  * encryption and decryption operations.
14
10
  * @param {Type.BlobLike} file - The file to upload
11
+ * @param {Type.EncryptionConfig} encryptionConfig - User-provided encryption configuration
12
+ * @param {Type.UploadOptions} [uploadOptions] - User-provided upload options
15
13
  * @returns {Promise<Type.AnyLink>} - The link to the uploaded file
16
14
  */
17
- export const encryptAndUpload = async (storachaClient, litClient, cryptoAdapter, file) => {
18
- const spaceDID = /** @type {Type.SpaceDID | undefined} */ (storachaClient.agent.currentSpace());
19
- if (!spaceDID)
15
+ export const encryptAndUpload = async (storachaClient, cryptoAdapter, file, encryptionConfig, uploadOptions = {}) => {
16
+ // Step 1: Validate required configuration
17
+ if (!encryptionConfig.spaceDID)
20
18
  throw new Error('No space selected!');
21
- const accessControlConditions = Lit.getAccessControlConditions(spaceDID);
22
- const encryptedPayload = await encryptFile(litClient, cryptoAdapter, file, accessControlConditions);
23
- const rootCid = await uploadEncryptedMetadata(storachaClient, encryptedPayload, accessControlConditions);
19
+ // Step 2: Encrypt the file using the crypto adapter
20
+ const encryptedPayload = await encryptFile(cryptoAdapter, file, encryptionConfig);
21
+ // Step 3: Build and upload the encrypted metadata to the Storacha network
22
+ const rootCid = await buildAndUploadEncryptedMetadata(storachaClient, encryptedPayload, cryptoAdapter, uploadOptions);
23
+ // Step 4: Return the root CID of the encrypted metadata
24
24
  return rootCid;
25
25
  };
26
26
  /**
27
27
  * Upload encrypted metadata to the Storacha network
28
28
  *
29
29
  * @param {import('@storacha/client').Client} storachaClient - The Storacha client
30
- * @param {Type.EncryptedPayload} encryptedPayload - The encrypted payload
31
- * @param {import('@lit-protocol/types').AccessControlConditions} accessControlConditions - The access control conditions
32
- * @param {object} [options] - The upload options
33
- * @param {boolean} [options.publishToFilecoin] - Whether to publish the data to Filecoin
30
+ * @param {Type.EncryptionPayload} encryptedPayload - The encrypted payload
31
+ * @param {Type.CryptoAdapter} cryptoAdapter - The crypto adapter for formatting metadata
32
+ * @param {Type.UploadOptions} [uploadOptions] - The upload options
34
33
  * @returns {Promise<Type.AnyLink>} - The link to the uploaded metadata
35
34
  */
36
- const uploadEncryptedMetadata = async (storachaClient, encryptedPayload, accessControlConditions, options = {
37
- publishToFilecoin: false,
38
- }) => {
39
- const { identityBoundCiphertext, plaintextKeyHash, encryptedBlobLike } = encryptedPayload;
35
+ const buildAndUploadEncryptedMetadata = async (storachaClient, encryptedPayload, cryptoAdapter, uploadOptions) => {
36
+ const { encryptedKey, metadata, encryptedBlobLike } = encryptedPayload;
40
37
  return storachaClient.uploadCAR({
41
38
  stream() {
42
39
  /** @type {any} */
@@ -50,45 +47,38 @@ const uploadEncryptedMetadata = async (storachaClient, encryptedPayload, accessC
50
47
  async flush(controller) {
51
48
  if (!root)
52
49
  throw new Error('missing root block');
53
- /** @type {Type.EncryptedMetadataInput} */
54
- const uploadData = {
55
- encryptedDataCID: root.cid.toString(),
56
- identityBoundCiphertext,
57
- plaintextKeyHash,
58
- accessControlConditions:
59
- /** @type {[Record<string, any>]} */ (
60
- /** @type {unknown} */ (accessControlConditions)),
61
- };
62
- const encryptedMetadata = EncryptedMetadata.create(uploadData);
63
- const { cid, bytes } = await encryptedMetadata.archiveBlock();
50
+ const { cid, bytes } = await cryptoAdapter.encodeMetadata(root.cid.toString(), encryptedKey, metadata);
64
51
  controller.enqueue({ cid, bytes });
65
52
  },
66
53
  }))
67
54
  .pipeThrough(new CARWriterStream());
68
55
  },
69
56
  }, {
70
- // if publishToFilecoin is false, the data won't be published to Filecoin, so we need to set pieceHasher to undefined
71
- ...(options.publishToFilecoin === true ? {} : { pieceHasher: undefined }),
57
+ ...uploadOptions,
58
+ // the encrypted data won't be published to Filecoin, so we need to set pieceHasher to undefined
59
+ pieceHasher: undefined,
72
60
  });
73
61
  };
74
62
  /**
75
- * Encrypt a file
63
+ * Encrypt a file using the crypto adapter and return the encrypted payload.
64
+ * The encrypted payload contains the encrypted file, the encrypted symmetric key, and the metadata.
76
65
  *
77
- * @param {import('@lit-protocol/lit-node-client').LitNodeClient} litClient - The Lit client
78
66
  * @param {Type.CryptoAdapter} cryptoAdapter - The crypto adapter responsible for performing
79
67
  * encryption and decryption operations.
80
68
  * @param {Type.BlobLike} file - The file to encrypt
81
- * @param {import('@lit-protocol/types').AccessControlConditions} accessControlConditions - The access control conditions
82
- * @returns {Promise<Type.EncryptedPayload>} - The encrypted file
69
+ * @param {Type.EncryptionConfig} encryptionConfig - The encryption configuration
70
+ * @returns {Promise<Type.EncryptionPayload>} - The encrypted file
83
71
  */
84
- const encryptFile = async (litClient, cryptoAdapter, file, accessControlConditions) => {
72
+ const encryptFile = async (cryptoAdapter, file, encryptionConfig) => {
73
+ // Step 1: Encrypt the file using the crypto adapter
85
74
  const { key, iv, encryptedStream } = await cryptoAdapter.encryptStream(file);
86
- // Combine key and initializationVector for Lit encryption
87
- const dataToEncrypt = base64.encode(new Uint8Array([...key, ...iv]));
88
- const { ciphertext, dataToEncryptHash } = await Lit.encryptString({ dataToEncrypt, accessControlConditions }, litClient);
75
+ // Step 2: Use crypto adapter to encrypt the symmetric key
76
+ const keyResult = await cryptoAdapter.encryptSymmetricKey(key, iv, encryptionConfig);
77
+ // Step 3: Return the encrypted payload
89
78
  return {
90
- identityBoundCiphertext: ciphertext,
91
- plaintextKeyHash: dataToEncryptHash,
79
+ strategy: keyResult.strategy,
80
+ encryptedKey: keyResult.encryptedKey,
81
+ metadata: keyResult.metadata,
92
82
  encryptedBlobLike: { stream: () => encryptedStream },
93
83
  };
94
84
  };
@@ -18,9 +18,7 @@ export function getSessionSigs(litClient: LitNodeClient, { wallet, accessControl
18
18
  */
19
19
  export function getPkpSessionSigs(litClient: LitNodeClient, { pkpPublicKey, authMethod, accessControlConditions, dataToEncryptHash, expiration, capabilityAuthSigs, }: Type.PkpSessionSignatureOptions): Promise<import("@lit-protocol/types").SessionSigsMap>;
20
20
  export { encryptString } from "@lit-protocol/encryption";
21
- export function getAccessControlConditions(spaceDID: import("@ucanto/core/schema").Schema<`did:key:${string}` & `did:${string}` & import("multiformats").Phantom<{
22
- protocol: "did:";
23
- }>, any>): import("@lit-protocol/types").AccessControlConditions;
21
+ export function getAccessControlConditions(spaceDID: Type.SpaceDID): import("@lit-protocol/types").AccessControlConditions;
24
22
  export function executeUcanValidationAction(litClient: LitNodeClient, options: Type.ExecuteUcanValidationOptions): Promise<any>;
25
23
  import { LitNodeClient } from '@lit-protocol/lit-node-client';
26
24
  import * as Type from '../types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"lit.d.ts","sourceRoot":"","sources":["../../src/protocols/lit.js"],"names":[],"mappings":"AAsCA;;GAEG;AACH,uDAQC;AAED;;;;GAIG;AACH,0CAJW,aAAa,2FACb,IAAI,CAAC,uBAAuB,GAC1B,OAAO,CAAC,OAAO,qBAAqB,EAAE,cAAc,CAAC,CAsDjE;AAED;;;;;;;GAOG;AACH,6CAJW,aAAa,6GACb,IAAI,CAAC,0BAA0B,GAC7B,OAAO,CAAC,OAAO,qBAAqB,EAAE,cAAc,CAAC,CAqCjE;;AAnIM;;WAFM,OAAO,qBAAqB,EAAE,uBAAuB,CAgBjE;AA6HM,uDAJI,aAAa,WACb,IAAI,CAAC,4BAA4B,gBA4B3C;8BA1L6B,+BAA+B;sBAUvC,aAAa"}
1
+ {"version":3,"file":"lit.d.ts","sourceRoot":"","sources":["../../src/protocols/lit.js"],"names":[],"mappings":"AAsCA;;GAEG;AACH,uDAQC;AAED;;;;GAIG;AACH,0CAJW,aAAa,2FACb,IAAI,CAAC,uBAAuB,GAC1B,OAAO,CAAC,OAAO,qBAAqB,EAAE,cAAc,CAAC,CAsDjE;AAED;;;;;;;GAOG;AACH,6CAJW,aAAa,6GACb,IAAI,CAAC,0BAA0B,GAC7B,OAAO,CAAC,OAAO,qBAAqB,EAAE,cAAc,CAAC,CAqCjE;;AAnIM,qDAHI,IAAI,CAAC,QAAQ,GACX,OAAO,qBAAqB,EAAE,uBAAuB,CAgBjE;AA6HM,uDAJI,aAAa,WACb,IAAI,CAAC,4BAA4B,gBA4B3C;8BA1L6B,+BAA+B;sBAUvC,aAAa"}