@storacha/encrypt-upload-client 1.1.65 → 1.1.66
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/dist/examples/decrypt-test.d.ts +2 -0
- package/dist/examples/decrypt-test.d.ts.map +1 -0
- package/dist/examples/decrypt-test.js +73 -0
- package/dist/examples/encrypt-test.d.ts +4 -0
- package/dist/examples/encrypt-test.d.ts.map +1 -0
- package/dist/examples/encrypt-test.js +61 -0
- package/dist/test/fixtures/test-fixtures.d.ts +28 -0
- package/dist/test/fixtures/test-fixtures.d.ts.map +1 -0
- package/dist/test/fixtures/test-fixtures.js +63 -0
- package/dist/test/https-enforcement.spec.d.ts +2 -0
- package/dist/test/https-enforcement.spec.d.ts.map +1 -0
- package/dist/test/https-enforcement.spec.js +125 -0
- package/dist/test/kms-crypto-adapter.spec.d.ts +2 -0
- package/dist/test/kms-crypto-adapter.spec.d.ts.map +1 -0
- package/dist/test/kms-crypto-adapter.spec.js +305 -0
- package/dist/test/lit-crypto-adapter.spec.d.ts +2 -0
- package/dist/test/lit-crypto-adapter.spec.d.ts.map +1 -0
- package/dist/test/lit-crypto-adapter.spec.js +120 -0
- package/dist/test/memory-efficiency.spec.d.ts +2 -0
- package/dist/test/memory-efficiency.spec.d.ts.map +1 -0
- package/dist/test/memory-efficiency.spec.js +93 -0
- package/dist/test/mocks/key-manager.d.ts +58 -0
- package/dist/test/mocks/key-manager.d.ts.map +1 -0
- package/dist/test/mocks/key-manager.js +137 -0
- package/dist/test/node-crypto-adapter.spec.d.ts +2 -0
- package/dist/test/node-crypto-adapter.spec.d.ts.map +1 -0
- package/dist/test/node-crypto-adapter.spec.js +103 -0
- package/dist/test/node-generic-crypto-adapter.spec.d.ts +2 -0
- package/dist/test/node-generic-crypto-adapter.spec.d.ts.map +1 -0
- package/dist/test/node-generic-crypto-adapter.spec.js +95 -0
- package/dist/tsconfig.spec.tsbuildinfo +1 -0
- package/package.json +2 -2
- package/dist/test/crypto-streaming.spec.js.map +0 -1
- package/dist/test/encrypted-metadata.spec.js.map +0 -1
- package/dist/test/factories.spec.js.map +0 -1
- package/dist/test/file-metadata.spec.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decrypt-test.d.ts","sourceRoot":"","sources":["../../examples/decrypt-test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import { CID } from 'multiformats';
|
|
4
|
+
import * as Client from '@storacha/client';
|
|
5
|
+
import * as Signer from '@ucanto/principal/ed25519';
|
|
6
|
+
import { StoreMemory } from '@storacha/client/stores/memory';
|
|
7
|
+
import { create } from '../src/index.js';
|
|
8
|
+
import { Wallet } from 'ethers';
|
|
9
|
+
import { serviceConf, receiptsEndpoint } from '../src/config/service.js';
|
|
10
|
+
import { createNodeLitAdapter } from '../src/crypto/factories.node.js';
|
|
11
|
+
import { LitNodeClient } from '@lit-protocol/lit-node-client';
|
|
12
|
+
import { extract } from '@ucanto/core/delegation';
|
|
13
|
+
dotenv.config();
|
|
14
|
+
async function main() {
|
|
15
|
+
// set up storacha client with a new agent
|
|
16
|
+
const cid = CID.parse('bafyreifhwqmspdjsy6rgcmcizgodv7bwskgiehjhdx7wukax3z5r7tz5ji');
|
|
17
|
+
const delegationCarBuffer = fs.readFileSync('delegation.car');
|
|
18
|
+
const wallet = new Wallet(process.env.WALLET_PK || '');
|
|
19
|
+
const principal = Signer.parse(process.env.DELEGATEE_AGENT_PK || '');
|
|
20
|
+
const store = new StoreMemory();
|
|
21
|
+
const client = await Client.create({
|
|
22
|
+
principal,
|
|
23
|
+
store,
|
|
24
|
+
serviceConf,
|
|
25
|
+
receiptsEndpoint,
|
|
26
|
+
});
|
|
27
|
+
// Set up Lit client
|
|
28
|
+
const litClient = new LitNodeClient({
|
|
29
|
+
litNetwork: 'datil-dev',
|
|
30
|
+
});
|
|
31
|
+
await litClient.connect();
|
|
32
|
+
const encryptedClient = await create({
|
|
33
|
+
storachaClient: client,
|
|
34
|
+
cryptoAdapter: createNodeLitAdapter(litClient),
|
|
35
|
+
});
|
|
36
|
+
const res = await extract(delegationCarBuffer);
|
|
37
|
+
if (res.error) {
|
|
38
|
+
throw new Error(`Failed to extract delegation: ${res.error.message}`);
|
|
39
|
+
}
|
|
40
|
+
const decryptDelegation = res.ok;
|
|
41
|
+
const decryptionCapability = decryptDelegation.capabilities.find((c) => c.can === 'space/content/decrypt');
|
|
42
|
+
if (!decryptionCapability) {
|
|
43
|
+
throw new Error('Failed to find decryption capability');
|
|
44
|
+
}
|
|
45
|
+
const spaceDID = /** @type {`did:key:${string}`} */ (decryptionCapability.with);
|
|
46
|
+
const decryptionConfig = {
|
|
47
|
+
wallet,
|
|
48
|
+
decryptDelegation,
|
|
49
|
+
spaceDID,
|
|
50
|
+
};
|
|
51
|
+
const decryptedContent = await encryptedClient.retrieveAndDecryptFile(cid, decryptionConfig);
|
|
52
|
+
const reader = decryptedContent.stream.getReader();
|
|
53
|
+
const decoder = new TextDecoder();
|
|
54
|
+
let result = '';
|
|
55
|
+
let done = false;
|
|
56
|
+
while (!done) {
|
|
57
|
+
const { value, done: isDone } = await reader.read();
|
|
58
|
+
done = isDone;
|
|
59
|
+
if (value) {
|
|
60
|
+
result += decoder.decode(value, { stream: true });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
console.log('================ RESULT ===================');
|
|
64
|
+
console.log(result);
|
|
65
|
+
console.log('===========================================');
|
|
66
|
+
}
|
|
67
|
+
main()
|
|
68
|
+
.then(() => process.exit(0))
|
|
69
|
+
.catch((err) => {
|
|
70
|
+
console.error(err);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=decrypt-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypt-test.d.ts","sourceRoot":"","sources":["../../examples/encrypt-test.js"],"names":[],"mappings":"AAeA,mDAAmD;AACnD,iCADY,MAAM,0DAQjB;wBAlBuB,2BAA2B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import { CarReader } from '@ipld/car';
|
|
4
|
+
import * as Client from '@storacha/client';
|
|
5
|
+
import { importDAG } from '@ucanto/core/delegation';
|
|
6
|
+
import * as Signer from '@ucanto/principal/ed25519';
|
|
7
|
+
import { StoreMemory } from '@storacha/client/stores/memory';
|
|
8
|
+
import * as EncryptClient from '../src/index.js';
|
|
9
|
+
import { serviceConf, receiptsEndpoint } from '../src/config/service.js';
|
|
10
|
+
import { createNodeLitAdapter } from '../src/crypto/factories.node.js';
|
|
11
|
+
import { LitNodeClient } from '@lit-protocol/lit-node-client';
|
|
12
|
+
dotenv.config();
|
|
13
|
+
/** @param {string} data Base64 encoded CAR file */
|
|
14
|
+
export async function parseProof(data) {
|
|
15
|
+
const blocks = [];
|
|
16
|
+
const reader = await CarReader.fromBytes(Buffer.from(data, 'base64'));
|
|
17
|
+
for await (const block of reader.blocks()) {
|
|
18
|
+
blocks.push(block);
|
|
19
|
+
}
|
|
20
|
+
return importDAG(blocks);
|
|
21
|
+
}
|
|
22
|
+
async function main() {
|
|
23
|
+
// set up storacha client with a new agent
|
|
24
|
+
const principal = Signer.parse(process.env.AGENT_PK || '');
|
|
25
|
+
const store = new StoreMemory();
|
|
26
|
+
const client = await Client.create({
|
|
27
|
+
principal,
|
|
28
|
+
store,
|
|
29
|
+
serviceConf,
|
|
30
|
+
receiptsEndpoint,
|
|
31
|
+
});
|
|
32
|
+
// now give Agent the delegation from the Space
|
|
33
|
+
const proof = await parseProof(process.env.PROOF || '');
|
|
34
|
+
const space = await client.addSpace(proof);
|
|
35
|
+
await client.setCurrentSpace(space.did());
|
|
36
|
+
// Set up Lit client
|
|
37
|
+
const litClient = new LitNodeClient({
|
|
38
|
+
litNetwork: 'datil-dev',
|
|
39
|
+
});
|
|
40
|
+
await litClient.connect();
|
|
41
|
+
const encryptedClient = await EncryptClient.create({
|
|
42
|
+
storachaClient: client,
|
|
43
|
+
cryptoAdapter: createNodeLitAdapter(litClient),
|
|
44
|
+
});
|
|
45
|
+
const fileContent = await fs.promises.readFile('./README.md');
|
|
46
|
+
const blob = new Blob([fileContent]);
|
|
47
|
+
// Create encryption config
|
|
48
|
+
const encryptionConfig = {
|
|
49
|
+
issuer: principal,
|
|
50
|
+
spaceDID: space.did(),
|
|
51
|
+
};
|
|
52
|
+
const link = await encryptedClient.encryptAndUploadFile(blob, encryptionConfig);
|
|
53
|
+
console.log(link);
|
|
54
|
+
}
|
|
55
|
+
main()
|
|
56
|
+
.then(() => process.exit(0))
|
|
57
|
+
.catch((err) => {
|
|
58
|
+
console.error(err);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=encrypt-test.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate mock RSA key pair for testing that works with Web Crypto API
|
|
3
|
+
*/
|
|
4
|
+
export function generateMockRSAKeyPair(): Promise<{
|
|
5
|
+
keyPair: CryptoKeyPair;
|
|
6
|
+
publicKeyPem: string;
|
|
7
|
+
}>;
|
|
8
|
+
/**
|
|
9
|
+
* Helper to create test fixtures
|
|
10
|
+
*/
|
|
11
|
+
export function createTestFixtures(): Promise<{
|
|
12
|
+
keyManagerServiceDID: ed25519.EdSigner;
|
|
13
|
+
spaceDID: `did:key:${string}`;
|
|
14
|
+
spaceSigner: ed25519.EdSigner;
|
|
15
|
+
issuer: ed25519.EdSigner;
|
|
16
|
+
keyPair: CryptoKeyPair;
|
|
17
|
+
publicKeyPem: string;
|
|
18
|
+
delegationProof: Server.API.Delegation<[{
|
|
19
|
+
with: `did:key:${string}`;
|
|
20
|
+
can: "space/encryption/setup";
|
|
21
|
+
}, {
|
|
22
|
+
with: `did:key:${string}`;
|
|
23
|
+
can: "space/encryption/key/decrypt";
|
|
24
|
+
}]>;
|
|
25
|
+
}>;
|
|
26
|
+
import { ed25519 } from '@ucanto/principal';
|
|
27
|
+
import * as Server from '@ucanto/server';
|
|
28
|
+
//# sourceMappingURL=test-fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-fixtures.d.ts","sourceRoot":"","sources":["../../../test/fixtures/test-fixtures.js"],"names":[],"mappings":"AAGA;;GAEG;AACH;;;GA+BC;AAED;;GAEG;AACH;;;;;;;;;;;;;;GAqCC;wBA9EuB,mBAAmB;wBADnB,gBAAgB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as Server from '@ucanto/server';
|
|
2
|
+
import { ed25519 } from '@ucanto/principal';
|
|
3
|
+
/**
|
|
4
|
+
* Generate mock RSA key pair for testing that works with Web Crypto API
|
|
5
|
+
*/
|
|
6
|
+
export async function generateMockRSAKeyPair() {
|
|
7
|
+
// Generate key pair using Web Crypto API first
|
|
8
|
+
const keyPair = await globalThis.crypto.subtle.generateKey({
|
|
9
|
+
name: 'RSA-OAEP',
|
|
10
|
+
modulusLength: 2048,
|
|
11
|
+
publicExponent: new Uint8Array([1, 0, 1]),
|
|
12
|
+
hash: 'SHA-256',
|
|
13
|
+
}, true, ['encrypt', 'decrypt']);
|
|
14
|
+
// Export public key to SPKI format (this will work with our adapter)
|
|
15
|
+
const publicKeyBuffer = await globalThis.crypto.subtle.exportKey('spki', keyPair.publicKey);
|
|
16
|
+
// Convert to proper PEM format using standard base64 (not multibase)
|
|
17
|
+
const base64String = Buffer.from(publicKeyBuffer).toString('base64');
|
|
18
|
+
// Format as proper PEM with line breaks every 64 characters like real KMS
|
|
19
|
+
const formattedBase64 = base64String.match(/.{1,64}/g)?.join('\n') || base64String;
|
|
20
|
+
const publicKeyPem = `-----BEGIN PUBLIC KEY-----\n${formattedBase64}\n-----END PUBLIC KEY-----`;
|
|
21
|
+
return {
|
|
22
|
+
keyPair,
|
|
23
|
+
publicKeyPem,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Helper to create test fixtures
|
|
28
|
+
*/
|
|
29
|
+
export async function createTestFixtures() {
|
|
30
|
+
// Create mock key manager service DID
|
|
31
|
+
const keyManagerServiceDID = await ed25519.generate();
|
|
32
|
+
// Create mock space DID - this will be the issuer
|
|
33
|
+
const spaceSigner = await ed25519.generate();
|
|
34
|
+
const spaceDID = spaceSigner.did();
|
|
35
|
+
// Generate mock RSA key pair
|
|
36
|
+
const { keyPair, publicKeyPem } = await generateMockRSAKeyPair();
|
|
37
|
+
// Create mock delegation proof - space delegates to itself (self-issued)
|
|
38
|
+
const delegationProof = await Server.delegate({
|
|
39
|
+
issuer: spaceSigner,
|
|
40
|
+
audience: spaceSigner, // Self-delegation for testing
|
|
41
|
+
capabilities: [
|
|
42
|
+
{
|
|
43
|
+
with: spaceDID,
|
|
44
|
+
can: 'space/encryption/setup',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
with: spaceDID,
|
|
48
|
+
can: 'space/encryption/key/decrypt',
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
expiration: Infinity,
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
keyManagerServiceDID,
|
|
55
|
+
spaceDID,
|
|
56
|
+
spaceSigner,
|
|
57
|
+
issuer: spaceSigner, // Use space signer as issuer
|
|
58
|
+
keyPair,
|
|
59
|
+
publicKeyPem,
|
|
60
|
+
delegationProof,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=test-fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"https-enforcement.spec.d.ts","sourceRoot":"","sources":["../../test/https-enforcement.spec.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { describe, test } from 'node:test';
|
|
3
|
+
import { KMSCryptoAdapter } from '../src/crypto/adapters/kms-crypto-adapter.js';
|
|
4
|
+
import { GenericAesCtrStreamingCrypto } from '../src/crypto/symmetric/generic-aes-ctr-streaming-crypto.js';
|
|
5
|
+
await describe('HTTPS Enforcement', async () => {
|
|
6
|
+
await describe('KMSCryptoAdapter Constructor', async () => {
|
|
7
|
+
await test('should accept valid HTTPS URL as string', async () => {
|
|
8
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
9
|
+
// Should not throw
|
|
10
|
+
const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://private.storacha.link', 'did:web:private.storacha.link');
|
|
11
|
+
assert(adapter instanceof KMSCryptoAdapter, 'Should create adapter successfully');
|
|
12
|
+
assert.strictEqual(adapter.keyManagerServiceURL.protocol, 'https:', 'Should store HTTPS protocol');
|
|
13
|
+
assert.strictEqual(adapter.keyManagerServiceURL.toString(), 'https://private.storacha.link/', 'Should store correct URL');
|
|
14
|
+
});
|
|
15
|
+
await test('should accept valid HTTPS URL object', async () => {
|
|
16
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
17
|
+
const httpsURL = new URL('https://example.com:8443/path');
|
|
18
|
+
// Should not throw
|
|
19
|
+
const adapter = new KMSCryptoAdapter(symmetricCrypto, httpsURL, 'did:web:example.com');
|
|
20
|
+
assert(adapter instanceof KMSCryptoAdapter, 'Should create adapter successfully');
|
|
21
|
+
assert.strictEqual(adapter.keyManagerServiceURL.protocol, 'https:', 'Should store HTTPS protocol');
|
|
22
|
+
assert.strictEqual(adapter.keyManagerServiceURL.toString(), 'https://example.com:8443/path', 'Should preserve URL structure');
|
|
23
|
+
});
|
|
24
|
+
await test('should reject HTTP URL string', async () => {
|
|
25
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
26
|
+
assert.throws(() => new KMSCryptoAdapter(symmetricCrypto, 'http://insecure.example.com', 'did:web:example.com'), /Key manager service must use HTTPS protocol for security/, 'Should reject HTTP protocol');
|
|
27
|
+
});
|
|
28
|
+
await test('should reject HTTP URL object', async () => {
|
|
29
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
30
|
+
const httpURL = new URL('http://insecure.example.com');
|
|
31
|
+
assert.throws(() => new KMSCryptoAdapter(symmetricCrypto, httpURL, 'did:web:example.com'), /Key manager service must use HTTPS protocol for security/, 'Should reject HTTP URL object');
|
|
32
|
+
});
|
|
33
|
+
await test('should reject other protocols', async () => {
|
|
34
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
35
|
+
const protocolTestCases = [
|
|
36
|
+
'ftp://example.com',
|
|
37
|
+
'ws://example.com',
|
|
38
|
+
'file://example.com',
|
|
39
|
+
'data:text/plain;base64,SGVsbG8=',
|
|
40
|
+
];
|
|
41
|
+
for (const testURL of protocolTestCases) {
|
|
42
|
+
assert.throws(() => new KMSCryptoAdapter(symmetricCrypto, testURL, 'did:web:example.com'), /Key manager service must use HTTPS protocol for security/, `Should reject protocol: ${testURL}`);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
await test('should provide helpful error message', async () => {
|
|
46
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
47
|
+
try {
|
|
48
|
+
new KMSCryptoAdapter(symmetricCrypto, 'http://example.com', 'did:web:example.com');
|
|
49
|
+
assert.fail('Should have thrown an error');
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
assert(error instanceof Error, 'Should throw Error instance');
|
|
53
|
+
assert(error.message.includes('Key manager service must use HTTPS protocol'), 'Should include main error message');
|
|
54
|
+
assert(error.message.includes('Received: http:'), 'Should include received protocol');
|
|
55
|
+
assert(error.message.includes('https://your-key-manager-service.com'), 'Should include example of correct format');
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
await test('should handle localhost development URLs correctly', async () => {
|
|
59
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
60
|
+
// Even localhost should require HTTPS for consistency
|
|
61
|
+
assert.throws(() => new KMSCryptoAdapter(symmetricCrypto, 'http://localhost:3000', 'did:web:localhost'), /Key manager service must use HTTPS protocol for security/, 'Should reject HTTP even for localhost');
|
|
62
|
+
// But HTTPS localhost should work
|
|
63
|
+
const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://localhost:3000', 'did:web:localhost');
|
|
64
|
+
assert(adapter instanceof KMSCryptoAdapter, 'Should accept HTTPS localhost');
|
|
65
|
+
});
|
|
66
|
+
await test('should handle invalid URL strings gracefully', async () => {
|
|
67
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
68
|
+
assert.throws(() => new KMSCryptoAdapter(symmetricCrypto, 'not-a-valid-url', 'did:web:example.com'), /Invalid URL/, 'Should throw URL parsing error for invalid URLs');
|
|
69
|
+
});
|
|
70
|
+
await test('should preserve all adapter functionality after HTTPS validation', async () => {
|
|
71
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
72
|
+
const adapter = new KMSCryptoAdapter(symmetricCrypto, 'https://private.storacha.link', 'did:web:private.storacha.link');
|
|
73
|
+
// Verify all expected methods exist
|
|
74
|
+
assert.strictEqual(typeof adapter.encryptStream, 'function', 'Should have encryptStream method');
|
|
75
|
+
assert.strictEqual(typeof adapter.decryptStream, 'function', 'Should have decryptStream method');
|
|
76
|
+
assert.strictEqual(typeof adapter.encryptSymmetricKey, 'function', 'Should have encryptSymmetricKey method');
|
|
77
|
+
assert.strictEqual(typeof adapter.decryptSymmetricKey, 'function', 'Should have decryptSymmetricKey method');
|
|
78
|
+
assert.strictEqual(typeof adapter.extractEncryptedMetadata, 'function', 'Should have extractEncryptedMetadata method');
|
|
79
|
+
assert.strictEqual(typeof adapter.getEncryptedKey, 'function', 'Should have getEncryptedKey method');
|
|
80
|
+
assert.strictEqual(typeof adapter.encodeMetadata, 'function', 'Should have encodeMetadata method');
|
|
81
|
+
// Verify adapter properties are set correctly
|
|
82
|
+
assert(adapter.symmetricCrypto === symmetricCrypto, 'Should store symmetric crypto reference');
|
|
83
|
+
assert.strictEqual(adapter.keyManagerServiceDID.did(), 'did:web:private.storacha.link', 'Should store gateway DID');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
await describe('Secure by Default Principle', async () => {
|
|
87
|
+
await test('should demonstrate secure by default - HTTPS is automatically used', async () => {
|
|
88
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
89
|
+
// All of these should work without any special configuration
|
|
90
|
+
const validHttpsUrls = [
|
|
91
|
+
'https://gateway.example.com',
|
|
92
|
+
'https://localhost:8080',
|
|
93
|
+
'https://192.168.1.100:3000',
|
|
94
|
+
'https://api.storacha.network:443/v1',
|
|
95
|
+
];
|
|
96
|
+
for (const url of validHttpsUrls) {
|
|
97
|
+
const adapter = new KMSCryptoAdapter(symmetricCrypto, url, 'did:web:example.com');
|
|
98
|
+
assert.strictEqual(adapter.keyManagerServiceURL.protocol, 'https:', `Should store HTTPS protocol for URL: ${url}`);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
await test('should require explicit insecure configuration to bypass HTTPS', async () => {
|
|
102
|
+
// This demonstrates that HTTP is never accidentally allowed
|
|
103
|
+
// If someone really needs HTTP (like for testing), they would need to
|
|
104
|
+
// modify our security validation code intentionally
|
|
105
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
106
|
+
const httpUrls = [
|
|
107
|
+
'http://example.com',
|
|
108
|
+
'http://localhost:3000',
|
|
109
|
+
'http://192.168.1.100:8080',
|
|
110
|
+
];
|
|
111
|
+
for (const url of httpUrls) {
|
|
112
|
+
assert.throws(() => new KMSCryptoAdapter(symmetricCrypto, url, 'did:web:example.com'), /Key manager service must use HTTPS protocol for security/, `Should reject HTTP URL: ${url}`);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
await test('should allow HTTP for testing when explicitly enabled', async () => {
|
|
116
|
+
// This demonstrates the testing escape hatch
|
|
117
|
+
const symmetricCrypto = new GenericAesCtrStreamingCrypto();
|
|
118
|
+
const adapter = new KMSCryptoAdapter(symmetricCrypto, 'http://localhost:8080', 'did:web:localhost', { allowInsecureHttp: true } // Explicit testing option
|
|
119
|
+
);
|
|
120
|
+
assert.strictEqual(adapter.keyManagerServiceURL.protocol, 'http:', 'Should allow HTTP when explicitly enabled for testing');
|
|
121
|
+
assert.strictEqual(adapter.keyManagerServiceURL.toString(), 'http://localhost:8080/', 'Should preserve HTTP URL when testing option is enabled');
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=https-enforcement.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kms-crypto-adapter.spec.d.ts","sourceRoot":"","sources":["../../test/kms-crypto-adapter.spec.js"],"names":[],"mappings":""}
|