@storacha/encrypt-upload-client 1.1.63 → 1.1.65

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 (36) hide show
  1. package/dist/test/crypto-streaming.spec.js.map +1 -0
  2. package/dist/test/encrypted-metadata.spec.js.map +1 -0
  3. package/dist/test/factories.spec.js.map +1 -0
  4. package/dist/test/file-metadata.spec.js.map +1 -0
  5. package/package.json +2 -2
  6. package/dist/examples/decrypt-test.d.ts +0 -2
  7. package/dist/examples/decrypt-test.d.ts.map +0 -1
  8. package/dist/examples/decrypt-test.js +0 -73
  9. package/dist/examples/encrypt-test.d.ts +0 -4
  10. package/dist/examples/encrypt-test.d.ts.map +0 -1
  11. package/dist/examples/encrypt-test.js +0 -61
  12. package/dist/test/fixtures/test-fixtures.d.ts +0 -28
  13. package/dist/test/fixtures/test-fixtures.d.ts.map +0 -1
  14. package/dist/test/fixtures/test-fixtures.js +0 -63
  15. package/dist/test/https-enforcement.spec.d.ts +0 -2
  16. package/dist/test/https-enforcement.spec.d.ts.map +0 -1
  17. package/dist/test/https-enforcement.spec.js +0 -125
  18. package/dist/test/kms-crypto-adapter.spec.d.ts +0 -2
  19. package/dist/test/kms-crypto-adapter.spec.d.ts.map +0 -1
  20. package/dist/test/kms-crypto-adapter.spec.js +0 -305
  21. package/dist/test/lit-crypto-adapter.spec.d.ts +0 -2
  22. package/dist/test/lit-crypto-adapter.spec.d.ts.map +0 -1
  23. package/dist/test/lit-crypto-adapter.spec.js +0 -120
  24. package/dist/test/memory-efficiency.spec.d.ts +0 -2
  25. package/dist/test/memory-efficiency.spec.d.ts.map +0 -1
  26. package/dist/test/memory-efficiency.spec.js +0 -93
  27. package/dist/test/mocks/key-manager.d.ts +0 -58
  28. package/dist/test/mocks/key-manager.d.ts.map +0 -1
  29. package/dist/test/mocks/key-manager.js +0 -137
  30. package/dist/test/node-crypto-adapter.spec.d.ts +0 -2
  31. package/dist/test/node-crypto-adapter.spec.d.ts.map +0 -1
  32. package/dist/test/node-crypto-adapter.spec.js +0 -103
  33. package/dist/test/node-generic-crypto-adapter.spec.d.ts +0 -2
  34. package/dist/test/node-generic-crypto-adapter.spec.d.ts.map +0 -1
  35. package/dist/test/node-generic-crypto-adapter.spec.js +0 -95
  36. package/dist/tsconfig.spec.tsbuildinfo +0 -1
@@ -1,305 +0,0 @@
1
- import './setup.js';
2
- import { test, describe } from 'node:test';
3
- import assert from 'node:assert';
4
- import * as Server from '@ucanto/server';
5
- import { base64 } from 'multiformats/bases/base64';
6
- import * as Space from '@storacha/capabilities/space';
7
- import { GenericAesCtrStreamingCrypto } from '../src/crypto/symmetric/generic-aes-ctr-streaming-crypto.js';
8
- import { KMSCryptoAdapter } from '../src/crypto/adapters/kms-crypto-adapter.js';
9
- import { createMockKeyManagerService, createMockKeyManagerServer, } from './mocks/key-manager.js';
10
- import { createTestFixtures } from './fixtures/test-fixtures.js';
11
- import { stringToUint8Array, streamToUint8Array, uint8ArrayToString, } from './helpers/test-file-utils.js';
12
- await describe('KMSCryptoAdapter', async () => {
13
- await describe('Unit Tests', async () => {
14
- await test('should delegate symmetric crypto operations to the injected implementation', async () => {
15
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
16
- const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://private.storacha.link', 'did:web:private.storacha.link');
17
- const originalText = 'Op, this is a test for KMS strategy-based encryption!';
18
- const blob = new Blob([stringToUint8Array(originalText)]);
19
- // Test that it delegates to the symmetric crypto implementation
20
- const { key, iv, encryptedStream } = await adapter.encryptStream(blob);
21
- assert(key instanceof Uint8Array, 'Key should be a Uint8Array');
22
- assert(iv instanceof Uint8Array, 'IV should be a Uint8Array');
23
- assert(encryptedStream instanceof ReadableStream, 'Encrypted stream should be a ReadableStream');
24
- // Test decryption delegation
25
- const decryptedStream = await adapter.decryptStream(encryptedStream, key, iv);
26
- const decryptedBytes = await streamToUint8Array(decryptedStream);
27
- const decryptedText = uint8ArrayToString(decryptedBytes);
28
- assert.strictEqual(decryptedText, originalText, 'Decrypted text should match original');
29
- });
30
- await test('should initialize KMS adapter with correct configuration', async () => {
31
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
32
- const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://private.storacha.link', 'did:web:private.storacha.link');
33
- // Test that the adapter can handle encryption options directly
34
- assert(typeof adapter.encryptSymmetricKey === 'function', 'encryptSymmetricKey should be a function');
35
- // Verify adapter constructor sets properties correctly
36
- assert(typeof adapter.keyManagerServiceDID === 'object', 'Adapter should have gateway DID object');
37
- assert.strictEqual(adapter.keyManagerServiceDID.did(), 'did:web:private.storacha.link', 'Adapter should have correct gateway DID');
38
- assert(adapter.keyManagerServiceURL instanceof URL, 'Adapter should have gateway URL');
39
- });
40
- await test('should handle metadata extraction with invalid CAR data', async () => {
41
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
42
- const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://private.storacha.link', 'did:web:private.storacha.link');
43
- // Test that the method exists
44
- assert(typeof adapter.extractEncryptedMetadata === 'function', 'extractEncryptedMetadata should be a function');
45
- assert(typeof adapter.getEncryptedKey === 'function', 'getEncryptedKey should be a function');
46
- // Should throw error for invalid CAR data
47
- const mockCar = new Uint8Array([1, 2, 3]);
48
- assert.throws(() => {
49
- adapter.extractEncryptedMetadata(mockCar);
50
- }, /Invalid CAR header format/, 'Should throw error for invalid CAR data');
51
- });
52
- await test('should sanitize space DID for KMS key ID', async () => {
53
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
54
- const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://mock-gateway.example.com', 'did:web:mock');
55
- const spaceDID = 'did:key:z6MkwDK3M4PxU1FqcSt6quBH1xRBSGnPRdQYP9B13h3Wq5X1';
56
- const sanitized = adapter.sanitizeSpaceDIDForKMSKeyId(spaceDID);
57
- assert.strictEqual(sanitized, 'z6MkwDK3M4PxU1FqcSt6quBH1xRBSGnPRdQYP9B13h3Wq5X1');
58
- assert(!sanitized.includes('did:key:'));
59
- });
60
- });
61
- await describe('Integration Tests', async () => {
62
- await test('should complete full encryption workflow with mocked private gateway', async () => {
63
- const fixtures = await createTestFixtures();
64
- const { keyManagerServiceDID, spaceDID, issuer, publicKeyPem, keyPair, delegationProof, } = fixtures;
65
- let setupCalled = false;
66
- let decryptCalled = false;
67
- let actualEncryptedKey = '';
68
- // Create mock gateway service that performs real RSA encryption/decryption
69
- const service = createMockKeyManagerService({
70
- mockPublicKey: publicKeyPem,
71
- onEncryptionSetup: (/** @type {any} */ input) => {
72
- setupCalled = true;
73
- assert.strictEqual(input.capability.with, spaceDID);
74
- assert.strictEqual(input.capability.can, 'space/encryption/setup');
75
- },
76
- onKeyDecrypt: (/** @type {any} */ input) => {
77
- decryptCalled = true;
78
- assert.strictEqual(input.capability.with, spaceDID);
79
- assert.strictEqual(input.capability.can, 'space/encryption/key/decrypt');
80
- },
81
- });
82
- // Override the decrypt handler to actually decrypt with the private key
83
- service.space.encryption.key.decrypt = Server.provide(Space.EncryptionKeyDecrypt, async (input) => {
84
- decryptCalled = true;
85
- assert.strictEqual(input.capability.with, spaceDID);
86
- assert.strictEqual(input.capability.can, 'space/encryption/key/decrypt');
87
- // Get the encrypted key from the request
88
- const encryptedKeyBytes = input.capability.nb.key;
89
- const encryptedSymmetricKey = base64.encode(encryptedKeyBytes);
90
- actualEncryptedKey = encryptedSymmetricKey;
91
- // Decrypt with RSA private key (simulate real KMS decryption)
92
- const encryptedBytes = encryptedKeyBytes;
93
- const decryptedBytes = await globalThis.crypto.subtle.decrypt({ name: 'RSA-OAEP' }, keyPair.privateKey, encryptedBytes);
94
- // Return the decrypted symmetric key as base64
95
- const decryptedKey = base64.encode(new Uint8Array(decryptedBytes));
96
- return Server.ok({
97
- decryptedSymmetricKey: decryptedKey,
98
- });
99
- });
100
- // Create mock gateway server (HTTPS by default)
101
- const keyManagerServiceServer = await createMockKeyManagerServer(service, keyManagerServiceDID, 5555);
102
- // Create KMS adapter with HTTP allowed for testing
103
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
104
- const adapter = new KMSCryptoAdapter(symmetricCrypto, keyManagerServiceServer.url, keyManagerServiceDID.did(), { allowInsecureHttp: true } // Allow HTTP for testing
105
- );
106
- try {
107
- // Create test file and encrypt it to get real symmetric keys
108
- const testFile = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
109
- const testBlob = new Blob([testFile], {
110
- type: 'application/octet-stream',
111
- });
112
- // Encrypt the file to get real symmetric keys
113
- const { key, iv } = await adapter.encryptStream(testBlob);
114
- const encryptionConfig = {
115
- issuer,
116
- spaceDID,
117
- location: 'us-central1',
118
- keyring: 'test-keyring',
119
- };
120
- // Test key encryption with real symmetric keys - this will call the mock setup
121
- const encryptResult = await adapter.encryptSymmetricKey(key, iv, encryptionConfig);
122
- assert(setupCalled, 'EncryptionSetup should have been called');
123
- assert.strictEqual(encryptResult.strategy, 'kms');
124
- const kmsMetadata =
125
- /** @type {import('../src/types.js').KMSKeyMetadata} */ (encryptResult.metadata);
126
- assert.strictEqual(kmsMetadata.space, spaceDID);
127
- assert.strictEqual(kmsMetadata.kms.provider, 'google-kms');
128
- assert.strictEqual(kmsMetadata.kms.algorithm, 'RSA-OAEP-2048-SHA256');
129
- assert(typeof encryptResult.encryptedKey === 'string');
130
- // Test key decryption - this will call the mock decrypt
131
- const decryptionConfig = {
132
- spaceDID,
133
- decryptDelegation: delegationProof,
134
- proofs: [],
135
- };
136
- const mockMetadata = {
137
- strategy: /** @type {'kms'} */ ('kms'),
138
- encryptedDataCID: 'bafybeid',
139
- encryptedSymmetricKey: encryptResult.encryptedKey,
140
- space: spaceDID,
141
- kms: kmsMetadata.kms,
142
- };
143
- const decryptResult = await adapter.decryptSymmetricKey(encryptResult.encryptedKey, {
144
- decryptionConfig,
145
- metadata: mockMetadata,
146
- resourceCID:
147
- /** @type {import('@storacha/upload-client/types').AnyLink} */ (
148
- /** @type {any} */ ('bafybeid')),
149
- issuer,
150
- audience: keyManagerServiceDID.did(),
151
- });
152
- // Verify the round-trip worked
153
- assert(setupCalled, 'EncryptionSetup should have been called');
154
- assert(decryptCalled, 'KeyDecrypt should have been called');
155
- assert(decryptResult.key instanceof Uint8Array, 'Decrypted key should be Uint8Array');
156
- assert(decryptResult.iv instanceof Uint8Array, 'Decrypted IV should be Uint8Array');
157
- // Most importantly: verify the decrypted keys match the original
158
- assert.deepStrictEqual(decryptResult.key, key, 'Decrypted key should match original key');
159
- assert.deepStrictEqual(decryptResult.iv, iv, 'Decrypted IV should match original IV');
160
- // Verify the encrypted key was actually encrypted (different from original)
161
- const originalCombined = adapter.symmetricCrypto.combineKeyAndIV(key, iv);
162
- const originalBase64 = base64.encode(originalCombined);
163
- assert.notStrictEqual(actualEncryptedKey, originalBase64, 'Encrypted key should be different from original');
164
- }
165
- catch (error) {
166
- console.error('Test failed with error:', error);
167
- throw error;
168
- }
169
- finally {
170
- // Clean up server
171
- await keyManagerServiceServer.close();
172
- }
173
- });
174
- await test('should handle encryption setup errors gracefully', async () => {
175
- const fixtures = await createTestFixtures();
176
- const { keyManagerServiceDID, spaceDID, issuer } = fixtures;
177
- // Create service that returns errors
178
- const service = createMockKeyManagerService({
179
- mockPublicKey: 'invalid',
180
- onEncryptionSetup: () => {
181
- // This will be called but service will return error
182
- },
183
- });
184
- // Override service to return error
185
- service.space.encryption.setup = Server.provide(Space.EncryptionSetup, async () => {
186
- return Server.error({
187
- name: 'SpaceNotProvisioned',
188
- message: 'Space is not provisioned for encryption',
189
- });
190
- });
191
- const keyManagerServiceServer = await createMockKeyManagerServer(service, keyManagerServiceDID, 5556);
192
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
193
- const adapter = new KMSCryptoAdapter(symmetricCrypto, keyManagerServiceServer.url, keyManagerServiceDID.did(), { allowInsecureHttp: true } // Allow HTTP for testing
194
- );
195
- try {
196
- const testKey = new Uint8Array(32).fill(1);
197
- const testIV = new Uint8Array(16).fill(2);
198
- const encryptionConfig = {
199
- issuer,
200
- spaceDID,
201
- };
202
- // Should throw error
203
- await assert.rejects(() => adapter.encryptSymmetricKey(testKey, testIV, encryptionConfig), /Space is not provisioned for encryption/);
204
- }
205
- finally {
206
- await keyManagerServiceServer.close();
207
- }
208
- });
209
- await test('should handle key decryption errors gracefully', async () => {
210
- const fixtures = await createTestFixtures();
211
- const { keyManagerServiceDID, spaceDID, issuer, delegationProof } = fixtures;
212
- // Create service that returns errors for decrypt
213
- const service = createMockKeyManagerService({
214
- mockPublicKey: 'mock-key',
215
- });
216
- // Override decrypt service to return error
217
- service.space.encryption.key.decrypt = Server.provide(Space.EncryptionKeyDecrypt, async () => {
218
- return Server.error({
219
- name: 'KeyNotFound',
220
- message: 'KMS key not found',
221
- });
222
- });
223
- const keyManagerServiceServer = await createMockKeyManagerServer(service, keyManagerServiceDID, 5557);
224
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
225
- const adapter = new KMSCryptoAdapter(symmetricCrypto, keyManagerServiceServer.url, keyManagerServiceDID.did(), { allowInsecureHttp: true } // Allow HTTP for testing
226
- );
227
- const decryptionOptions = {
228
- spaceDID,
229
- decryptDelegation: delegationProof,
230
- };
231
- const mockKey = new Uint8Array([1, 2, 3]); // test value as bytes
232
- const mockKeyString = base64.encode(mockKey);
233
- const mockMetadata = {
234
- strategy: /** @type {'kms'} */ ('kms'),
235
- encryptedDataCID: 'bafybeid',
236
- key: mockKey, // use bytes, not string
237
- space: spaceDID,
238
- kms: {
239
- provider: /** @type {'google-kms'} */ ('google-kms'),
240
- keyId: 'test-key',
241
- algorithm: /** @type {'RSA-OAEP-2048-SHA256'} */ ('RSA-OAEP-2048-SHA256'),
242
- },
243
- };
244
- const decryptConfigs = /** @type {any} */ ({
245
- decryptionConfig: decryptionOptions,
246
- metadata: mockMetadata,
247
- delegationCAR: new Uint8Array(),
248
- resourceCID: 'bafybeid',
249
- issuer,
250
- audience: keyManagerServiceDID.did(),
251
- });
252
- try {
253
- // Should throw error
254
- await assert.rejects(() => adapter.decryptSymmetricKey(mockKeyString, decryptConfigs), /KMS key not found/);
255
- }
256
- finally {
257
- await keyManagerServiceServer.close();
258
- }
259
- });
260
- });
261
- await describe('Validation Tests', async () => {
262
- await test('should validate required decryption parameters', async () => {
263
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
264
- const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://mock-gateway.example.com', 'did:web:mock');
265
- const invalidConfigs = /** @type {any} */ ({
266
- decryptionConfig: {}, // Missing spaceDID and decryptDelegation
267
- metadata: { strategy: 'kms' },
268
- delegationCAR: new Uint8Array(),
269
- resourceCID: 'bafybeid',
270
- issuer: null,
271
- audience: 'did:web:mock',
272
- });
273
- await assert.rejects(() => adapter.decryptSymmetricKey('key', invalidConfigs), /SpaceDID and decryptDelegation are required/);
274
- });
275
- await test('should validate issuer is provided', async () => {
276
- const fixtures = await createTestFixtures();
277
- const { spaceDID, delegationProof } = fixtures;
278
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
279
- const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://mock-gateway.example.com', 'did:web:mock');
280
- const invalidConfigs = /** @type {any} */ ({
281
- decryptionConfig: { spaceDID, decryptDelegation: delegationProof },
282
- metadata: { strategy: 'kms' },
283
- delegationCAR: new Uint8Array(),
284
- resourceCID: 'bafybeid',
285
- issuer: null, // Missing issuer
286
- audience: 'did:web:mock',
287
- });
288
- await assert.rejects(() => adapter.decryptSymmetricKey('key', invalidConfigs), /Issuer is required/);
289
- });
290
- await test('should reject non-KMS metadata', async () => {
291
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
292
- const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://mock-gateway.example.com', 'did:web:mock');
293
- const invalidConfigs = /** @type {any} */ ({
294
- decryptionOptions: { spaceDID: 'did:key:test', delegationProof: {} },
295
- metadata: { strategy: 'lit' }, // Wrong strategy
296
- delegationCAR: new Uint8Array(),
297
- resourceCID: 'bafybeid',
298
- issuer: {},
299
- audience: 'did:web:mock',
300
- });
301
- await assert.rejects(() => adapter.decryptSymmetricKey('key', invalidConfigs), /KMSCryptoAdapter can only handle KMS metadata/);
302
- });
303
- });
304
- });
305
- //# sourceMappingURL=kms-crypto-adapter.spec.js.map
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=lit-crypto-adapter.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lit-crypto-adapter.spec.d.ts","sourceRoot":"","sources":["../../test/lit-crypto-adapter.spec.js"],"names":[],"mappings":""}
@@ -1,120 +0,0 @@
1
- import './setup.js';
2
- import { test, describe } from 'node:test';
3
- import assert from 'node:assert';
4
- import { GenericAesCtrStreamingCrypto } from '../src/crypto/symmetric/generic-aes-ctr-streaming-crypto.js';
5
- import { NodeAesCbcCrypto } from '../src/crypto/symmetric/node-aes-cbc-crypto.js';
6
- import { LitCryptoAdapter } from '../src/crypto/adapters/lit-crypto-adapter.js';
7
- import { stringToUint8Array, streamToUint8Array, uint8ArrayToString, } from './helpers/test-file-utils.js';
8
- // Mock Lit client - cast to any for testing
9
- const mockLitClient = /** @type {any} */ ({
10
- // Add mock methods as needed
11
- });
12
- await describe('LitCryptoAdapter', async () => {
13
- await describe('Generic AES-CTR Crypto Implementation', async () => {
14
- await test('should delegate symmetric crypto operations to the generic implementation', async () => {
15
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
16
- const adapter = new LitCryptoAdapter(symmetricCrypto, mockLitClient);
17
- const originalText = 'Op, this is a test for strategy-based encryption!';
18
- const blob = new Blob([stringToUint8Array(originalText)]);
19
- // Test that it delegates to the symmetric crypto implementation
20
- const { key, iv, encryptedStream } = await adapter.encryptStream(blob);
21
- assert(key instanceof Uint8Array, 'Key should be a Uint8Array');
22
- assert(iv instanceof Uint8Array, 'IV should be a Uint8Array');
23
- assert(encryptedStream instanceof ReadableStream, 'Encrypted stream should be a ReadableStream');
24
- // Test decryption delegation
25
- const decryptedStream = await adapter.decryptStream(encryptedStream, key, iv);
26
- const decryptedBytes = await streamToUint8Array(decryptedStream);
27
- const decryptedText = uint8ArrayToString(decryptedBytes);
28
- assert.strictEqual(decryptedText, originalText, 'Decrypted text should match original');
29
- });
30
- await test('should initialize Generic Lit adapter with correct configuration', async () => {
31
- const symmetricCrypto = new GenericAesCtrStreamingCrypto();
32
- const adapter = new LitCryptoAdapter(symmetricCrypto, mockLitClient);
33
- // Test that the adapter has the required methods
34
- assert(typeof adapter.encryptSymmetricKey === 'function', 'encryptSymmetricKey should be a function');
35
- assert(typeof adapter.decryptSymmetricKey === 'function', 'decryptSymmetricKey should be a function');
36
- // Verify adapter has the lit client
37
- assert.strictEqual(adapter.litClient, mockLitClient, 'Adapter should store the Lit client');
38
- // Verify it uses the correct crypto implementation
39
- assert(adapter.symmetricCrypto instanceof GenericAesCtrStreamingCrypto, 'Should use GenericAesCtrStreamingCrypto');
40
- });
41
- });
42
- await describe('Node.js AES-CBC Crypto Implementation (Legacy)', async () => {
43
- await test('should delegate symmetric crypto operations to the Node.js implementation', async () => {
44
- const symmetricCrypto = new NodeAesCbcCrypto();
45
- const adapter = new LitCryptoAdapter(symmetricCrypto, mockLitClient);
46
- const originalText = 'Op, this is a test for legacy Node.js encryption!';
47
- const blob = new Blob([stringToUint8Array(originalText)]);
48
- // Test that it delegates to the symmetric crypto implementation
49
- const { key, iv, encryptedStream } = await adapter.encryptStream(blob);
50
- assert(key instanceof Uint8Array, 'Key should be a Uint8Array');
51
- assert(iv instanceof Uint8Array, 'IV should be a Uint8Array');
52
- assert(encryptedStream instanceof ReadableStream, 'Encrypted stream should be a ReadableStream');
53
- // Test decryption delegation
54
- const decryptedStream = await adapter.decryptStream(encryptedStream, key, iv);
55
- const decryptedBytes = await streamToUint8Array(decryptedStream);
56
- const decryptedText = uint8ArrayToString(decryptedBytes);
57
- assert.strictEqual(decryptedText, originalText, 'Decrypted text should match original');
58
- });
59
- await test('should initialize Node.js Lit adapter with correct configuration', async () => {
60
- const symmetricCrypto = new NodeAesCbcCrypto();
61
- const adapter = new LitCryptoAdapter(symmetricCrypto, mockLitClient);
62
- // Test that the adapter has the required methods
63
- assert(typeof adapter.encryptSymmetricKey === 'function', 'encryptSymmetricKey should be a function');
64
- assert(typeof adapter.decryptSymmetricKey === 'function', 'decryptSymmetricKey should be a function');
65
- // Verify adapter has the lit client
66
- assert.strictEqual(adapter.litClient, mockLitClient, 'Adapter should store the Lit client');
67
- // Verify it uses the correct crypto implementation
68
- assert(adapter.symmetricCrypto instanceof NodeAesCbcCrypto, 'Should use NodeAesCbcCrypto');
69
- });
70
- });
71
- await describe('Cross-Implementation Compatibility', async () => {
72
- await test('should demonstrate algorithm differences between implementations', async () => {
73
- const genericCrypto = new GenericAesCtrStreamingCrypto();
74
- const nodeCrypto = new NodeAesCbcCrypto();
75
- const genericAdapter = new LitCryptoAdapter(genericCrypto, mockLitClient);
76
- const nodeAdapter = new LitCryptoAdapter(nodeCrypto, mockLitClient);
77
- const originalText = 'Test data for algorithm comparison';
78
- const blob = new Blob([stringToUint8Array(originalText)]);
79
- // Encrypt with both adapters
80
- const genericResult = await genericAdapter.encryptStream(blob);
81
- const nodeResult = await nodeAdapter.encryptStream(blob);
82
- // Convert streams to bytes
83
- const genericEncrypted = await streamToUint8Array(genericResult.encryptedStream);
84
- const nodeEncrypted = await streamToUint8Array(nodeResult.encryptedStream);
85
- // Verify they produce different results (different algorithms)
86
- assert.notDeepEqual(genericEncrypted, nodeEncrypted, 'AES-CTR and AES-CBC should produce different encrypted outputs');
87
- // Verify both can decrypt their own data
88
- const genericDecryptStream = new ReadableStream({
89
- start(controller) {
90
- controller.enqueue(genericEncrypted);
91
- controller.close();
92
- },
93
- });
94
- const nodeDecryptStream = new ReadableStream({
95
- start(controller) {
96
- controller.enqueue(nodeEncrypted);
97
- controller.close();
98
- },
99
- });
100
- const genericDecrypted = await genericAdapter.decryptStream(genericDecryptStream, genericResult.key, genericResult.iv);
101
- const nodeDecrypted = await nodeAdapter.decryptStream(nodeDecryptStream, nodeResult.key, nodeResult.iv);
102
- const genericDecryptedBytes = await streamToUint8Array(genericDecrypted);
103
- const nodeDecryptedBytes = await streamToUint8Array(nodeDecrypted);
104
- // Both should decrypt to the same original text
105
- assert.strictEqual(uint8ArrayToString(genericDecryptedBytes), originalText, 'Generic adapter should decrypt correctly');
106
- assert.strictEqual(uint8ArrayToString(nodeDecryptedBytes), originalText, 'Node adapter should decrypt correctly');
107
- console.log('Both crypto implementations work with Lit adapter but produce different encrypted outputs');
108
- });
109
- await test('should verify factory function behavior', async () => {
110
- const { createGenericLitAdapter, createNodeLitAdapter } = await import('../src/crypto/factories.node.js');
111
- const genericAdapter = createGenericLitAdapter(mockLitClient);
112
- const nodeAdapter = createNodeLitAdapter(mockLitClient);
113
- // Verify factory functions create adapters with correct crypto implementations
114
- assert(genericAdapter.symmetricCrypto instanceof GenericAesCtrStreamingCrypto, 'Generic factory should create adapter with GenericAesCtrStreamingCrypto');
115
- assert(nodeAdapter.symmetricCrypto instanceof NodeAesCbcCrypto, 'Node factory should create adapter with NodeAesCbcCrypto');
116
- console.log('Factory functions create adapters with correct crypto implementations');
117
- });
118
- });
119
- });
120
- //# sourceMappingURL=lit-crypto-adapter.spec.js.map
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=memory-efficiency.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory-efficiency.spec.d.ts","sourceRoot":"","sources":["../../test/memory-efficiency.spec.js"],"names":[],"mappings":""}
@@ -1,93 +0,0 @@
1
- import './setup.js';
2
- import { test, describe } from 'node:test';
3
- import assert from 'node:assert';
4
- import { GenericAesCtrStreamingCrypto } from '../src/crypto/symmetric/generic-aes-ctr-streaming-crypto.js';
5
- import { createTestFile } from './helpers/test-file-utils.js';
6
- /**
7
- * These tests demonstrate why streaming is necessary for large files.
8
- * They show that buffered approaches fail with memory errors while streaming succeeds.
9
- */
10
- await describe('Memory Efficiency - Why Streaming Matters', async () => {
11
- await test('should show streaming handles progressively larger files', async () => {
12
- const streamingCrypto = new GenericAesCtrStreamingCrypto();
13
- // Test with multiple sizes to show streaming scales linearly
14
- const testSizes = [5, 10, 15, 20, 50, 100, 500, 1000]; // MB - sizes that would challenge buffered approaches
15
- for (const sizeMB of testSizes) {
16
- console.log(`Processing ${sizeMB}MB file...`);
17
- const testFile = createTestFile(sizeMB);
18
- const startTime = Date.now();
19
- const { encryptedStream } = await streamingCrypto.encryptStream(testFile);
20
- let processedBytes = 0;
21
- let chunkCount = 0;
22
- const reader = encryptedStream.getReader();
23
- try {
24
- // eslint-disable-next-line no-constant-condition
25
- while (true) {
26
- const { done, value } = await reader.read();
27
- if (done)
28
- break;
29
- processedBytes += value.length;
30
- chunkCount++;
31
- }
32
- }
33
- finally {
34
- reader.releaseLock();
35
- }
36
- const processingTime = Date.now() - startTime;
37
- const throughput = processedBytes / 1024 / 1024 / (processingTime / 1000); // MB/s
38
- assert.strictEqual(processedBytes, testFile.size, `Should process entire ${sizeMB}MB file`);
39
- console.log(`✓ ${sizeMB}MB: ${chunkCount} chunks, ${throughput.toFixed(1)} MB/s`);
40
- }
41
- console.log('DEMONSTRATED: Streaming handles large files with consistent performance');
42
- });
43
- await test('should project memory behavior for realistic file sizes', async () => {
44
- const streamingCrypto = new GenericAesCtrStreamingCrypto();
45
- // Test with a size we can actually handle to project larger files
46
- const testFile = createTestFile(5); // 5MB
47
- const getMemoryUsage = () => {
48
- if (globalThis.gc)
49
- globalThis.gc();
50
- return process.memoryUsage ? process.memoryUsage().heapUsed : 0;
51
- };
52
- const baseMemory = getMemoryUsage();
53
- const { encryptedStream } = await streamingCrypto.encryptStream(testFile);
54
- let peakMemoryDelta = 0;
55
- let processedBytes = 0;
56
- const reader = encryptedStream.getReader();
57
- try {
58
- // eslint-disable-next-line no-constant-condition
59
- while (true) {
60
- const { done, value } = await reader.read();
61
- if (done)
62
- break;
63
- processedBytes += value.length;
64
- // Sample memory usage
65
- const currentMemory = getMemoryUsage();
66
- const memoryDelta = currentMemory - baseMemory;
67
- peakMemoryDelta = Math.max(peakMemoryDelta, memoryDelta);
68
- }
69
- }
70
- finally {
71
- reader.releaseLock();
72
- }
73
- const peakMemoryMB = peakMemoryDelta / 1024 / 1024;
74
- const fileSize = testFile.size / 1024 / 1024;
75
- const memoryEfficiency = (peakMemoryDelta / testFile.size) * 100;
76
- console.log(`File size: ${fileSize.toFixed(1)}MB`);
77
- console.log(`Peak memory delta: ${peakMemoryMB.toFixed(2)}MB`);
78
- console.log(`Memory efficiency: ${memoryEfficiency.toFixed(1)}% of file size`);
79
- // Project to larger file sizes
80
- console.log('\nProjected memory usage:');
81
- const projectedSizes = [100, 1000, 5000]; // MB = 100MB, 1GB, 5GB
82
- for (const sizeMB of projectedSizes) {
83
- const projectedMemory = (memoryEfficiency / 100) * sizeMB;
84
- const sizeLabel = sizeMB >= 1000 ? `${sizeMB / 1000}GB` : `${sizeMB}MB`;
85
- console.log(` ${sizeLabel}: ~${projectedMemory.toFixed(1)}MB memory`);
86
- }
87
- // Memory should be bounded (much less than file size)
88
- assert(peakMemoryMB < fileSize, 'Streaming should use less memory than file size');
89
- assert(memoryEfficiency < 50, 'Memory usage should be less than 50% of file size');
90
- console.log('DEMONSTRATED: Streaming memory usage scales sub-linearly with file size');
91
- });
92
- });
93
- //# sourceMappingURL=memory-efficiency.spec.js.map
@@ -1,58 +0,0 @@
1
- /**
2
- * Create mock KMS service with proper capability handlers
3
- *
4
- * @param {object} options
5
- * @param {string} options.mockPublicKey - Mock RSA public key in PEM format
6
- * @param {string} [options.mockProvider] - Mock KMS provider
7
- * @param {string} [options.mockAlgorithm] - Mock algorithm
8
- * @param {Function} [options.onEncryptionSetup] - Optional callback for setup calls
9
- * @param {Function} [options.onKeyDecrypt] - Optional callback for decrypt calls
10
- */
11
- export function createMockKeyManagerService(options: {
12
- mockPublicKey: string;
13
- mockProvider?: string | undefined;
14
- mockAlgorithm?: string | undefined;
15
- onEncryptionSetup?: Function | undefined;
16
- onKeyDecrypt?: Function | undefined;
17
- }): {
18
- space: {
19
- encryption: {
20
- setup: Server.ServiceMethod<Server.API.Capability<"space/encryption/setup", `did:key:${string}` & `did:${string}` & Server.API.Phantom<{
21
- protocol: "did:";
22
- }>, Partial<Pick<{
23
- location: string | undefined;
24
- keyring: string | undefined;
25
- }, "location" | "keyring">>>, {
26
- publicKey: string;
27
- provider: string;
28
- algorithm: string;
29
- }, Server.API.Failure & {
30
- name: string;
31
- message: string;
32
- }>;
33
- key: {
34
- decrypt: Server.ServiceMethod<Server.API.Capability<"space/encryption/key/decrypt", `did:key:${string}` & `did:${string}` & Server.API.Phantom<{
35
- protocol: "did:";
36
- }>, Pick<{
37
- key: Uint8Array<ArrayBufferLike>;
38
- }, "key">>, {
39
- decryptedSymmetricKey: string;
40
- }, Server.API.Failure & {
41
- name: string;
42
- message: string;
43
- }>;
44
- };
45
- };
46
- };
47
- };
48
- /**
49
- * Create a mock key manager service server
50
- *
51
- * @param {object} service - The service object with capability handlers
52
- * @param {*} keyManagerServiceDID - The key manager service DID keypair
53
- * @param {number} port - The port to listen on
54
- * @param {boolean} [useHttps] - Whether to use HTTPS URLs (testing HTTPS scenarios)
55
- */
56
- export function createMockKeyManagerServer(service: object, keyManagerServiceDID: any, port: number, useHttps?: boolean): Promise<any>;
57
- import * as Server from '@ucanto/server';
58
- //# sourceMappingURL=key-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"key-manager.d.ts","sourceRoot":"","sources":["../../../test/mocks/key-manager.js"],"names":[],"mappings":"AAMA;;;;;;;;;GASG;AACH,qDANG;IAAwB,aAAa,EAA7B,MAAM;IACW,YAAY;IACZ,aAAa;IACX,iBAAiB;IACjB,YAAY;CACzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwEA;AAED;;;;;;;GAOG;AACH,oDALW,MAAM,wBACN,GAAC,QACD,MAAM,aACN,OAAO,gBA6DjB;wBA3JuB,gBAAgB"}