@reclaimprotocol/attestor-core 3.0.1
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/README.md +39 -0
- package/lib/avs/abis/avsDirectoryABI.d.ts +60 -0
- package/lib/avs/abis/avsDirectoryABI.js +344 -0
- package/lib/avs/abis/delegationABI.d.ts +126 -0
- package/lib/avs/abis/delegationABI.js +5 -0
- package/lib/avs/abis/registryABI.d.ts +136 -0
- package/lib/avs/abis/registryABI.js +729 -0
- package/lib/avs/client/create-claim-on-avs.d.ts +10 -0
- package/lib/avs/client/create-claim-on-avs.js +147 -0
- package/lib/avs/config.d.ts +7 -0
- package/lib/avs/config.js +24 -0
- package/lib/avs/contracts/ReclaimServiceManager.d.ts +697 -0
- package/lib/avs/contracts/ReclaimServiceManager.js +3 -0
- package/lib/avs/contracts/common.d.ts +21 -0
- package/lib/avs/contracts/common.js +3 -0
- package/lib/avs/contracts/factories/ReclaimServiceManager__factory.d.ts +888 -0
- package/lib/avs/contracts/factories/ReclaimServiceManager__factory.js +1174 -0
- package/lib/avs/contracts/factories/index.d.ts +1 -0
- package/lib/avs/contracts/factories/index.js +9 -0
- package/lib/avs/contracts/index.d.ts +3 -0
- package/lib/avs/contracts/index.js +30 -0
- package/lib/avs/tests/test.operator.d.ts +11 -0
- package/lib/avs/tests/test.operator.js +313 -0
- package/lib/avs/tests/utils.d.ts +2 -0
- package/lib/avs/tests/utils.js +50 -0
- package/lib/avs/types/index.d.ts +55 -0
- package/lib/avs/types/index.js +3 -0
- package/lib/avs/utils/contracts.d.ts +21 -0
- package/lib/avs/utils/contracts.js +38 -0
- package/lib/avs/utils/register.d.ts +27 -0
- package/lib/avs/utils/register.js +76 -0
- package/lib/avs/utils/tasks.d.ts +22 -0
- package/lib/avs/utils/tasks.js +45 -0
- package/lib/client/create-claim.d.ts +5 -0
- package/lib/client/create-claim.js +357 -0
- package/lib/client/index.d.ts +3 -0
- package/lib/client/index.js +20 -0
- package/lib/client/tunnels/make-rpc-tcp-tunnel.d.ts +16 -0
- package/lib/client/tunnels/make-rpc-tcp-tunnel.js +60 -0
- package/lib/client/tunnels/make-rpc-tls-tunnel.d.ts +25 -0
- package/lib/client/tunnels/make-rpc-tls-tunnel.js +135 -0
- package/lib/client/utils/attestor-pool.d.ts +6 -0
- package/lib/client/utils/attestor-pool.js +28 -0
- package/lib/client/utils/client-socket.d.ts +9 -0
- package/lib/client/utils/client-socket.js +77 -0
- package/lib/client/utils/message-handler.d.ts +4 -0
- package/lib/client/utils/message-handler.js +93 -0
- package/lib/config/index.d.ts +23 -0
- package/lib/config/index.js +35 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +39 -0
- package/lib/proto/api.d.ts +414 -0
- package/lib/proto/api.js +2756 -0
- package/lib/providers/http/index.d.ts +3 -0
- package/lib/providers/http/index.js +472 -0
- package/lib/providers/http/utils.d.ts +44 -0
- package/lib/providers/http/utils.js +302 -0
- package/lib/providers/index.d.ts +4 -0
- package/lib/providers/index.js +11 -0
- package/lib/scripts/check-avs-registration.d.ts +1 -0
- package/lib/scripts/check-avs-registration.js +28 -0
- package/lib/scripts/generate-provider-types.d.ts +5 -0
- package/lib/scripts/generate-provider-types.js +82 -0
- package/lib/scripts/generate-receipt.d.ts +9 -0
- package/lib/scripts/generate-receipt.js +93 -0
- package/lib/scripts/register-avs-operator.d.ts +1 -0
- package/lib/scripts/register-avs-operator.js +6 -0
- package/lib/scripts/start-server.d.ts +1 -0
- package/lib/scripts/start-server.js +6 -0
- package/lib/scripts/verify-root-ca.d.ts +1 -0
- package/lib/scripts/verify-root-ca.js +51 -0
- package/lib/server/create-server.d.ts +7 -0
- package/lib/server/create-server.js +85 -0
- package/lib/server/handlers/claimTunnel.d.ts +2 -0
- package/lib/server/handlers/claimTunnel.js +55 -0
- package/lib/server/handlers/completeClaimOnChain.d.ts +2 -0
- package/lib/server/handlers/completeClaimOnChain.js +28 -0
- package/lib/server/handlers/createClaimOnChain.d.ts +2 -0
- package/lib/server/handlers/createClaimOnChain.js +31 -0
- package/lib/server/handlers/createTunnel.d.ts +2 -0
- package/lib/server/handlers/createTunnel.js +65 -0
- package/lib/server/handlers/disconnectTunnel.d.ts +2 -0
- package/lib/server/handlers/disconnectTunnel.js +10 -0
- package/lib/server/handlers/index.d.ts +4 -0
- package/lib/server/handlers/index.js +18 -0
- package/lib/server/handlers/init.d.ts +2 -0
- package/lib/server/handlers/init.js +21 -0
- package/lib/server/index.d.ts +4 -0
- package/lib/server/index.js +21 -0
- package/lib/server/socket.d.ts +11 -0
- package/lib/server/socket.js +95 -0
- package/lib/server/tunnels/make-tcp-tunnel.d.ts +20 -0
- package/lib/server/tunnels/make-tcp-tunnel.js +182 -0
- package/lib/server/utils/apm.d.ts +11 -0
- package/lib/server/utils/apm.js +39 -0
- package/lib/server/utils/assert-valid-claim-request.d.ts +29 -0
- package/lib/server/utils/assert-valid-claim-request.js +189 -0
- package/lib/server/utils/config-env.d.ts +1 -0
- package/lib/server/utils/config-env.js +7 -0
- package/lib/server/utils/generics.d.ts +22 -0
- package/lib/server/utils/generics.js +59 -0
- package/lib/server/utils/iso.d.ts +1 -0
- package/lib/server/utils/iso.js +260 -0
- package/lib/server/utils/keep-alive.d.ts +7 -0
- package/lib/server/utils/keep-alive.js +42 -0
- package/lib/server/utils/process-handshake.d.ts +13 -0
- package/lib/server/utils/process-handshake.js +179 -0
- package/lib/server/utils/verify-server-certificates.d.ts +7 -0
- package/lib/server/utils/verify-server-certificates.js +102 -0
- package/lib/tests/describe-with-server.d.ts +21 -0
- package/lib/tests/describe-with-server.js +67 -0
- package/lib/tests/mock-provider-server.d.ts +13 -0
- package/lib/tests/mock-provider-server.js +65 -0
- package/lib/tests/mocks.d.ts +4 -0
- package/lib/tests/mocks.js +23 -0
- package/lib/tests/test.claim-creation.d.ts +1 -0
- package/lib/tests/test.claim-creation.js +187 -0
- package/lib/tests/test.http-parser.d.ts +1 -0
- package/lib/tests/test.http-parser.js +118 -0
- package/lib/tests/test.http-provider-utils.d.ts +1 -0
- package/lib/tests/test.http-provider-utils.js +1932 -0
- package/lib/tests/test.http-provider.d.ts +1 -0
- package/lib/tests/test.http-provider.js +43 -0
- package/lib/tests/test.rpc-communication.d.ts +1 -0
- package/lib/tests/test.rpc-communication.js +64 -0
- package/lib/tests/test.rpc-tunnel.d.ts +1 -0
- package/lib/tests/test.rpc-tunnel.js +168 -0
- package/lib/tests/test.signatures.d.ts +1 -0
- package/lib/tests/test.signatures.js +24 -0
- package/lib/tests/test.tcp-tunnel.d.ts +1 -0
- package/lib/tests/test.tcp-tunnel.js +64 -0
- package/lib/tests/test.zk.d.ts +1 -0
- package/lib/tests/test.zk.js +169 -0
- package/lib/tests/utils.d.ts +12 -0
- package/lib/tests/utils.js +49 -0
- package/lib/types/claims.d.ts +64 -0
- package/lib/types/claims.js +3 -0
- package/lib/types/client.d.ts +136 -0
- package/lib/types/client.js +3 -0
- package/lib/types/general.d.ts +39 -0
- package/lib/types/general.js +3 -0
- package/lib/types/handlers.d.ts +10 -0
- package/lib/types/handlers.js +3 -0
- package/lib/types/index.d.ts +9 -0
- package/lib/types/index.js +26 -0
- package/lib/types/providers.d.ts +135 -0
- package/lib/types/providers.gen.d.ts +414 -0
- package/lib/types/providers.gen.js +14 -0
- package/lib/types/providers.js +3 -0
- package/lib/types/rpc.d.ts +35 -0
- package/lib/types/rpc.js +3 -0
- package/lib/types/signatures.d.ts +28 -0
- package/lib/types/signatures.js +3 -0
- package/lib/types/tunnel.d.ts +18 -0
- package/lib/types/tunnel.js +3 -0
- package/lib/types/zk.d.ts +16 -0
- package/lib/types/zk.js +3 -0
- package/lib/utils/benchmark.d.ts +1 -0
- package/lib/utils/benchmark.js +70 -0
- package/lib/utils/claims.d.ts +33 -0
- package/lib/utils/claims.js +112 -0
- package/lib/utils/env.d.ts +3 -0
- package/lib/utils/env.js +20 -0
- package/lib/utils/error.d.ts +27 -0
- package/lib/utils/error.js +43 -0
- package/lib/utils/generics.d.ts +112 -0
- package/lib/utils/generics.js +348 -0
- package/lib/utils/http-parser.d.ts +55 -0
- package/lib/utils/http-parser.js +249 -0
- package/lib/utils/index.d.ts +10 -0
- package/lib/utils/index.js +27 -0
- package/lib/utils/logger.d.ts +13 -0
- package/lib/utils/logger.js +100 -0
- package/lib/utils/prepare-packets.d.ts +16 -0
- package/lib/utils/prepare-packets.js +61 -0
- package/lib/utils/redactions.d.ts +41 -0
- package/lib/utils/redactions.js +111 -0
- package/lib/utils/retries.d.ts +12 -0
- package/lib/utils/retries.js +28 -0
- package/lib/utils/signatures/eth.d.ts +2 -0
- package/lib/utils/signatures/eth.js +33 -0
- package/lib/utils/signatures/index.d.ts +5 -0
- package/lib/utils/signatures/index.js +11 -0
- package/lib/utils/socket-base.d.ts +21 -0
- package/lib/utils/socket-base.js +89 -0
- package/lib/utils/tls.d.ts +2 -0
- package/lib/utils/tls.js +32 -0
- package/lib/utils/validation.d.ts +2 -0
- package/lib/utils/validation.js +46 -0
- package/lib/utils/ws.d.ts +12 -0
- package/lib/utils/ws.js +21 -0
- package/lib/utils/zk.d.ts +50 -0
- package/lib/utils/zk.js +282 -0
- package/lib/window-rpc/index.d.ts +3 -0
- package/lib/window-rpc/index.js +20 -0
- package/lib/window-rpc/setup-window-rpc.d.ts +5 -0
- package/lib/window-rpc/setup-window-rpc.js +239 -0
- package/lib/window-rpc/types.d.ts +184 -0
- package/lib/window-rpc/types.js +3 -0
- package/lib/window-rpc/utils.d.ts +13 -0
- package/lib/window-rpc/utils.js +76 -0
- package/lib/window-rpc/window-rpc-zk.d.ts +11 -0
- package/lib/window-rpc/window-rpc-zk.js +72 -0
- package/package.json +117 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const client_1 = require("src/client");
|
|
4
|
+
const describe_with_server_1 = require("src/tests/describe-with-server");
|
|
5
|
+
const utils_1 = require("src/tests/utils");
|
|
6
|
+
jest.setTimeout(300000);
|
|
7
|
+
(0, describe_with_server_1.describeWithServer)('HTTP Provider', opts => {
|
|
8
|
+
afterEach(async () => {
|
|
9
|
+
await (0, utils_1.verifyNoDirectRevealLeaks)();
|
|
10
|
+
});
|
|
11
|
+
it('should create claim with template params', async () => {
|
|
12
|
+
var _a;
|
|
13
|
+
const resp = await (0, client_1.createClaimOnAttestor)({
|
|
14
|
+
name: 'http',
|
|
15
|
+
params: {
|
|
16
|
+
url: 'https://example.{{param1}}/',
|
|
17
|
+
method: 'GET',
|
|
18
|
+
responseMatches: [{
|
|
19
|
+
type: 'regex',
|
|
20
|
+
value: '<title.*?(?<domain>{{param2}} Domain)<\\/title>',
|
|
21
|
+
}],
|
|
22
|
+
responseRedactions: [{
|
|
23
|
+
xPath: './html/head/{{param3}}',
|
|
24
|
+
}],
|
|
25
|
+
paramValues: {
|
|
26
|
+
param1: 'com',
|
|
27
|
+
param2: 'Example',
|
|
28
|
+
param3: 'title'
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
secretParams: {
|
|
32
|
+
cookieStr: '<cookie-str>'
|
|
33
|
+
},
|
|
34
|
+
ownerPrivateKey: opts.privateKeyHex,
|
|
35
|
+
client: opts.client,
|
|
36
|
+
zkEngine: 'gnark'
|
|
37
|
+
});
|
|
38
|
+
expect(resp.error).toBeUndefined();
|
|
39
|
+
expect((_a = resp.claim) === null || _a === void 0 ? void 0 : _a.context)
|
|
40
|
+
.toContain('0x3bfcf3bf17b83b9c37756d9becf87f76cad712304a23d3335f78e1cc96e83d1f');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5odHRwLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3RzL3Rlc3QuaHR0cC1wcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHVDQUFrRDtBQUNsRCx5RUFBbUU7QUFDbkUsMkNBQTJEO0FBRTNELElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTyxDQUFDLENBQUE7QUFFeEIsSUFBQSx5Q0FBa0IsRUFBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLEVBQUU7SUFFMUMsU0FBUyxDQUFDLEtBQUssSUFBRyxFQUFFO1FBQ25CLE1BQU0sSUFBQSxpQ0FBeUIsR0FBRSxDQUFBO0lBQ2xDLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLDBDQUEwQyxFQUFFLEtBQUssSUFBRyxFQUFFOztRQUN4RCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUEsOEJBQXFCLEVBQUM7WUFDeEMsSUFBSSxFQUFFLE1BQU07WUFDWixNQUFNLEVBQUU7Z0JBQ1AsR0FBRyxFQUFFLDZCQUE2QjtnQkFDbEMsTUFBTSxFQUFFLEtBQUs7Z0JBQ2IsZUFBZSxFQUFFLENBQUM7d0JBQ2pCLElBQUksRUFBRSxPQUFPO3dCQUNiLEtBQUssRUFBRSxpREFBaUQ7cUJBQ3hELENBQUM7Z0JBQ0Ysa0JBQWtCLEVBQUUsQ0FBQzt3QkFDcEIsS0FBSyxFQUFFLHdCQUF3QjtxQkFDL0IsQ0FBQztnQkFDRixXQUFXLEVBQUU7b0JBQ1osTUFBTSxFQUFFLEtBQUs7b0JBQ2IsTUFBTSxFQUFFLFNBQVM7b0JBQ2pCLE1BQU0sRUFBRSxPQUFPO2lCQUNmO2FBQ0Q7WUFDRCxZQUFZLEVBQUU7Z0JBQ2IsU0FBUyxFQUFFLGNBQWM7YUFDekI7WUFDRCxlQUFlLEVBQUUsSUFBSSxDQUFDLGFBQWE7WUFDbkMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLFFBQVEsRUFBQyxPQUFPO1NBQ2hCLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDbEMsTUFBTSxDQUFDLE1BQUEsSUFBSSxDQUFDLEtBQUssMENBQUUsT0FBTyxDQUFDO2FBQ3pCLFNBQVMsQ0FBQyxvRUFBb0UsQ0FBQyxDQUFBO0lBQ2xGLENBQUMsQ0FBQyxDQUFBO0FBQ0gsQ0FBQyxDQUFDLENBQUEifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const client_1 = require("src/client");
|
|
4
|
+
const describe_with_server_1 = require("src/tests/describe-with-server");
|
|
5
|
+
const utils_1 = require("src/utils");
|
|
6
|
+
const ws_1 = require("ws");
|
|
7
|
+
(0, describe_with_server_1.describeWithServer)('RPC Communication', opts => {
|
|
8
|
+
const { getClientOnServer } = opts;
|
|
9
|
+
let client;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
client = opts.client;
|
|
12
|
+
});
|
|
13
|
+
it('should successfully initialise a session', async () => {
|
|
14
|
+
await expect(client.waitForInit()).resolves.toBeUndefined();
|
|
15
|
+
expect(client.isInitialised).toBe(true);
|
|
16
|
+
// ensure the server has our client
|
|
17
|
+
expect(getClientOnServer()).toBeTruthy();
|
|
18
|
+
});
|
|
19
|
+
it('should gracefully handle terminated connection during init', async () => {
|
|
20
|
+
await client.terminateConnection();
|
|
21
|
+
client = new client_1.AttestorClient({
|
|
22
|
+
logger: utils_1.logger,
|
|
23
|
+
// a URL without a WS server
|
|
24
|
+
url: `ws://localhost:${opts.mockhttpsServerPort}`
|
|
25
|
+
});
|
|
26
|
+
await expect(client.waitForInit()).rejects.toHaveProperty('code');
|
|
27
|
+
});
|
|
28
|
+
it('should gracefully handle connection termination', async () => {
|
|
29
|
+
const err = new utils_1.AttestorError('ERROR_INTERNAL', 'Test error', { abcd: 1 });
|
|
30
|
+
const waitForEnd = new Promise(resolve => {
|
|
31
|
+
client.addEventListener('connection-terminated', d => {
|
|
32
|
+
resolve(d.data);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
const ws = getClientOnServer();
|
|
36
|
+
await ws.terminateConnection(err);
|
|
37
|
+
const recvErr = await waitForEnd;
|
|
38
|
+
expect(recvErr).toEqual(err);
|
|
39
|
+
expect(client.isOpen).not.toBe(ws_1.WebSocket.OPEN);
|
|
40
|
+
});
|
|
41
|
+
it('should terminate connection to server', async () => {
|
|
42
|
+
const ws = getClientOnServer();
|
|
43
|
+
const waitForEnd = new Promise(resolve => {
|
|
44
|
+
ws.addEventListener('connection-terminated', d => {
|
|
45
|
+
resolve(d.data);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
await client.terminateConnection();
|
|
49
|
+
await waitForEnd;
|
|
50
|
+
});
|
|
51
|
+
it('should handle RPC error response', async () => {
|
|
52
|
+
const err = new utils_1.AttestorError('ERROR_INTERNAL', 'Test error', { abcd: 1 });
|
|
53
|
+
const ws = getClientOnServer();
|
|
54
|
+
ws.addEventListener('rpc-request', ev => {
|
|
55
|
+
ev.stopImmediatePropagation();
|
|
56
|
+
ev.data.respond(err);
|
|
57
|
+
});
|
|
58
|
+
await expect(client.rpc('createTunnel', {
|
|
59
|
+
host: 'localhost',
|
|
60
|
+
port: 9999,
|
|
61
|
+
})).rejects.toMatchObject(err);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5ycGMtY29tbXVuaWNhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0cy90ZXN0LnJwYy1jb21tdW5pY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsdUNBQTJDO0FBQzNDLHlFQUFtRTtBQUNuRSxxQ0FBaUQ7QUFDakQsMkJBQThCO0FBRTlCLElBQUEseUNBQWtCLEVBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLEVBQUU7SUFFOUMsTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsSUFBSSxDQUFBO0lBRWxDLElBQUksTUFBc0IsQ0FBQTtJQUMxQixVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2YsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUE7SUFDckIsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsMENBQTBDLEVBQUUsS0FBSyxJQUFHLEVBQUU7UUFDeEQsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxDQUFBO1FBQzNELE1BQU0sQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3ZDLG1DQUFtQztRQUNuQyxNQUFNLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFBO0lBQ3pDLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLDREQUE0RCxFQUFFLEtBQUssSUFBRyxFQUFFO1FBQzFFLE1BQU0sTUFBTSxDQUFDLG1CQUFtQixFQUFFLENBQUE7UUFDbEMsTUFBTSxHQUFHLElBQUksdUJBQWMsQ0FBQztZQUMzQixNQUFNLEVBQU4sY0FBTTtZQUNOLDRCQUE0QjtZQUM1QixHQUFHLEVBQUUsa0JBQWtCLElBQUksQ0FBQyxtQkFBbUIsRUFBRTtTQUNqRCxDQUFDLENBQUE7UUFDRixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMs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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const client_1 = require("src/client");
|
|
4
|
+
const make_rpc_tcp_tunnel_1 = require("src/client/tunnels/make-rpc-tcp-tunnel");
|
|
5
|
+
const make_rpc_tls_tunnel_1 = require("src/client/tunnels/make-rpc-tls-tunnel");
|
|
6
|
+
const describe_with_server_1 = require("src/tests/describe-with-server");
|
|
7
|
+
const utils_1 = require("src/tests/utils");
|
|
8
|
+
const utils_2 = require("src/utils");
|
|
9
|
+
(0, describe_with_server_1.describeWithServer)('RPC Tunnel', opts => {
|
|
10
|
+
const { mockHttpsServer, getClientOnServer } = opts;
|
|
11
|
+
let client;
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
client = opts.client;
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await client.terminateConnection();
|
|
17
|
+
});
|
|
18
|
+
it('should connect to a server via RPC tunnel', async () => {
|
|
19
|
+
// setup tunnel for listening & then
|
|
20
|
+
// connect to it via RPC
|
|
21
|
+
const tunnel = await (0, make_rpc_tcp_tunnel_1.makeRpcTcpTunnel)({ tunnelId: 1, client });
|
|
22
|
+
await client.rpc('createTunnel', {
|
|
23
|
+
id: 1,
|
|
24
|
+
host: 'localhost',
|
|
25
|
+
port: opts.mockhttpsServerPort,
|
|
26
|
+
geoLocation: ''
|
|
27
|
+
});
|
|
28
|
+
const ws = getClientOnServer();
|
|
29
|
+
const socketTunnel = ws === null || ws === void 0 ? void 0 : ws.tunnels[1];
|
|
30
|
+
expect(socketTunnel).toBeTruthy();
|
|
31
|
+
await tunnel.close();
|
|
32
|
+
// check that the server actually closed the tunnel
|
|
33
|
+
// upon our request
|
|
34
|
+
await expect(socketTunnel === null || socketTunnel === void 0 ? void 0 : socketTunnel.write(Buffer.from('hello'))).rejects.toMatchObject({
|
|
35
|
+
code: 'ERR_STREAM_WRITE_AFTER_END'
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe('TLS', () => {
|
|
39
|
+
it('should do a TLS handshake via RPC tunnel', async () => {
|
|
40
|
+
const ws = getClientOnServer();
|
|
41
|
+
const tunnel = await (0, make_rpc_tls_tunnel_1.makeRpcTlsTunnel)({
|
|
42
|
+
request: {
|
|
43
|
+
id: 1,
|
|
44
|
+
host: 'localhost',
|
|
45
|
+
port: opts.mockhttpsServerPort,
|
|
46
|
+
},
|
|
47
|
+
tlsOpts: {
|
|
48
|
+
verifyServerCertificate: false,
|
|
49
|
+
},
|
|
50
|
+
logger: client.logger,
|
|
51
|
+
connect(initMessages) {
|
|
52
|
+
client.sendMessage(...initMessages);
|
|
53
|
+
// ensure that the client hello message
|
|
54
|
+
// was sent to the server along the
|
|
55
|
+
// "createTunnel" request -- that saves
|
|
56
|
+
// us a round-trip
|
|
57
|
+
expect(initMessages[1].tunnelMessage)
|
|
58
|
+
.toBeTruthy();
|
|
59
|
+
return client;
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
expect(ws === null || ws === void 0 ? void 0 : ws.tunnels[1]).toBeTruthy();
|
|
63
|
+
await tunnel.close();
|
|
64
|
+
});
|
|
65
|
+
it('should setup a 0-RTT TLS connection', async () => {
|
|
66
|
+
let client2;
|
|
67
|
+
const tunnel = await (0, make_rpc_tls_tunnel_1.makeRpcTlsTunnel)({
|
|
68
|
+
request: {
|
|
69
|
+
id: 1,
|
|
70
|
+
host: 'localhost',
|
|
71
|
+
port: opts.mockhttpsServerPort,
|
|
72
|
+
},
|
|
73
|
+
tlsOpts: {
|
|
74
|
+
verifyServerCertificate: false,
|
|
75
|
+
},
|
|
76
|
+
logger: client.logger,
|
|
77
|
+
connect(initMessages) {
|
|
78
|
+
client2 = new client_1.AttestorClient({
|
|
79
|
+
url: opts.serverUrl,
|
|
80
|
+
logger: utils_2.logger.child({ client: 2 }),
|
|
81
|
+
initMessages
|
|
82
|
+
});
|
|
83
|
+
return client2;
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
await tunnel.close();
|
|
87
|
+
await (client2 === null || client2 === void 0 ? void 0 : client2.terminateConnection());
|
|
88
|
+
});
|
|
89
|
+
it('should gracefully handle a TLS disconnection alert', async () => {
|
|
90
|
+
let socket;
|
|
91
|
+
mockHttpsServer.server.once('secureConnection', s => {
|
|
92
|
+
socket = s;
|
|
93
|
+
});
|
|
94
|
+
let closeResolve;
|
|
95
|
+
await (0, make_rpc_tls_tunnel_1.makeRpcTlsTunnel)({
|
|
96
|
+
request: {
|
|
97
|
+
id: 1,
|
|
98
|
+
host: 'localhost',
|
|
99
|
+
port: opts.mockhttpsServerPort,
|
|
100
|
+
},
|
|
101
|
+
tlsOpts: {
|
|
102
|
+
verifyServerCertificate: false,
|
|
103
|
+
},
|
|
104
|
+
logger: client.logger,
|
|
105
|
+
connect(initMessages) {
|
|
106
|
+
client.sendMessage(...initMessages);
|
|
107
|
+
return client;
|
|
108
|
+
},
|
|
109
|
+
onClose(err) {
|
|
110
|
+
closeResolve === null || closeResolve === void 0 ? void 0 : closeResolve(err);
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
await (0, utils_1.delay)(100);
|
|
114
|
+
expect(socket).toBeTruthy();
|
|
115
|
+
socket === null || socket === void 0 ? void 0 : socket.end();
|
|
116
|
+
const err = await new Promise((resolve) => {
|
|
117
|
+
closeResolve = resolve;
|
|
118
|
+
});
|
|
119
|
+
// since it was a graceful close, there should be no error
|
|
120
|
+
expect(err).toBeUndefined();
|
|
121
|
+
});
|
|
122
|
+
it('should handle TLS handshake errors', async () => {
|
|
123
|
+
await expect((0, make_rpc_tls_tunnel_1.makeRpcTlsTunnel)({
|
|
124
|
+
request: {
|
|
125
|
+
id: 1,
|
|
126
|
+
host: 'localhost',
|
|
127
|
+
port: opts.mockhttpsServerPort,
|
|
128
|
+
},
|
|
129
|
+
tlsOpts: {
|
|
130
|
+
applicationLayerProtocols: [
|
|
131
|
+
'invalid-protocol'
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
logger: client.logger,
|
|
135
|
+
connect(initMessages) {
|
|
136
|
+
client.sendMessage(...initMessages);
|
|
137
|
+
return client;
|
|
138
|
+
},
|
|
139
|
+
})).rejects.toMatchObject({
|
|
140
|
+
message: /NO_APPLICATION_PROTOCOL/
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
it('should handle tunnel creation errors', async () => {
|
|
144
|
+
await expect((0, make_rpc_tls_tunnel_1.makeRpcTlsTunnel)({
|
|
145
|
+
request: {
|
|
146
|
+
id: 1,
|
|
147
|
+
host: 'localhost',
|
|
148
|
+
port: opts.mockhttpsServerPort,
|
|
149
|
+
// invalid geo location
|
|
150
|
+
geoLocation: 'XZ'
|
|
151
|
+
},
|
|
152
|
+
tlsOpts: {
|
|
153
|
+
applicationLayerProtocols: [
|
|
154
|
+
'invalid-protocol'
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
logger: client.logger,
|
|
158
|
+
connect(initMessages) {
|
|
159
|
+
client.sendMessage(...initMessages);
|
|
160
|
+
return client;
|
|
161
|
+
},
|
|
162
|
+
})).rejects.toMatchObject({
|
|
163
|
+
message: /NO_APPLICATION_PROTOCOL/
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5ycGMtdHVubmVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3RzL3Rlc3QucnBjLXR1bm5lbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHVDQUEyQztBQUMzQyxnRkFBeUU7QUFDekUsZ0ZBQXlFO0FBQ3pFLHlFQUFtRTtBQUNuRSwyQ0FBdUM7QUFDdkMscUNBQWtDO0FBR2xDLElBQUEseUNBQWtCLEVBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxFQUFFO0lBRXZDLE1BQU0sRUFBRSxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyxJQUFJLENBQUE7SUFFbkQsSUFBSSxNQUFzQixDQUFBO0lBQzFCLFVBQVUsQ0FBQyxLQUFLLElBQUcsRUFBRTtRQUNwQixNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQTtJQUNyQixDQUFDLENBQUMsQ0FBQTtJQUVGLFNBQVMsQ0FBQyxLQUFLLElBQUcsRUFBRTtRQUNuQixNQUFNLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxDQUFBO0lBQ25DLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLDJDQUEyQyxFQUFFLEtBQUssSUFBRyxFQUFFO1FBQ3pELG9DQUFvQztRQUNwQyx3QkFBd0I7UUFDeEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFBLHNDQUFnQixFQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQzlELE1BQU0sTUFBTSxDQUFDLEdBQUcsQ0FDZixjQUFjLEVBQ2Q7WUFDQyxFQUFFLEVBQUUsQ0FBQztZQUNMLElBQUksRUFBRSxXQUFXO1lBQ2pCLElBQUksRUFBRSxJQUFJLENBQUMsbUJBQW1CO1lBQzlCLFdBQVcsRUFBRSxFQUFFO1NBQ2YsQ0FDRCxDQUFBO1FBRUQsTUFBTSxFQUFFLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQTtRQUM5QixNQUFNLFlBQVksR0FBRyxFQUFFLGFBQUYsRUFBRSx1QkFBRixFQUFFLENB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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ethers_1 = require("ethers");
|
|
4
|
+
const api_1 = require("src/proto/api");
|
|
5
|
+
const signatures_1 = require("src/utils/signatures");
|
|
6
|
+
const ALGS = [
|
|
7
|
+
{
|
|
8
|
+
title: 'ETH',
|
|
9
|
+
algorithm: signatures_1.SIGNATURES[api_1.ServiceSignatureType.SERVICE_SIGNATURE_TYPE_ETH]
|
|
10
|
+
}
|
|
11
|
+
];
|
|
12
|
+
describe.each(ALGS)('$title Signatures', ({ algorithm }) => {
|
|
13
|
+
it('should sign & verify', async () => {
|
|
14
|
+
const alice = ethers_1.Wallet.createRandom();
|
|
15
|
+
const data = Buffer.from('{"a":"123","b":123}', 'utf8');
|
|
16
|
+
const signature = await algorithm.sign(data, alice.privateKey);
|
|
17
|
+
const addr = algorithm.getAddress(ethers_1.utils.arrayify(alice.publicKey));
|
|
18
|
+
let res = await algorithm.verify(data, signature, addr);
|
|
19
|
+
expect(res).toBeTruthy();
|
|
20
|
+
res = await algorithm.verify(data, ethers_1.utils.hexlify(signature), addr);
|
|
21
|
+
expect(res).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5zaWduYXR1cmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3RzL3Rlc3Quc2lnbmF0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLG1DQUFzQztBQUN0Qyx1Q0FBb0Q7QUFDcEQscURBQWlEO0FBRWpELE1BQU0sSUFBSSxHQUFHO0lBQ1o7UUFDQyxLQUFLLEVBQUUsS0FBSztRQUNaLFNBQVMsRUFBRSx1QkFBVSxDQUFDLDBCQUFvQixDQUFDLDBCQUEwQixDQUFDO0tBQ3RFO0NBQ0QsQ0FBQTtBQUVELFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFFMUQsRUFBRSxDQUFDLHNCQUFzQixFQUFFLEtBQUssSUFBRyxFQUFFO1FBRXBDLE1BQU0sS0FBSyxHQUFHLGVBQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQTtRQUVuQyxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQ3ZELE1BQU0sU0FBUyxHQUFHLE1BQU0sU0FBUyxDQUFDLElBQUksQ0FDckMsSUFBSSxFQUNKLEtBQUssQ0FBQyxVQUFVLENBQ2hCLENBQUE7UUFFRCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLGNBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUE7UUFDbEUsSUFBSSxHQUFHLEdBQUcsTUFBTSxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFFdkQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFBO1FBQ3hCLEdBQUcsR0FBRyxNQUFNLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLGNBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFFbEUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFBO0lBQ3pCLENBQUMsQ0FBQyxDQUFBO0FBQ0gsQ0FBQyxDQUFDLENBQUEifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tls_1 = require("@reclaimprotocol/tls");
|
|
4
|
+
const server_1 = require("src/server");
|
|
5
|
+
const utils_1 = require("src/utils");
|
|
6
|
+
const DEMO_GEO_LOCATIONS = ['in', 'us'];
|
|
7
|
+
jest.setTimeout(15000);
|
|
8
|
+
describe('TCP Tunnel', () => {
|
|
9
|
+
it.each([...DEMO_GEO_LOCATIONS, 'none'])('should generate a session using a geoLocation (%s)', async (geoLocation) => {
|
|
10
|
+
const resParser = (0, utils_1.makeHttpResponseParser)();
|
|
11
|
+
let resolvePromise;
|
|
12
|
+
let rejectPromise;
|
|
13
|
+
const session = await (0, server_1.makeTcpTunnel)({
|
|
14
|
+
host: 'lumtest.com',
|
|
15
|
+
port: 80,
|
|
16
|
+
geoLocation: geoLocation === 'none' ? '' : geoLocation,
|
|
17
|
+
logger: utils_1.logger,
|
|
18
|
+
onClose(err) {
|
|
19
|
+
rejectPromise === null || rejectPromise === void 0 ? void 0 : rejectPromise(err || new Error('session closed'));
|
|
20
|
+
},
|
|
21
|
+
onMessage(data) {
|
|
22
|
+
resParser.onChunk(data);
|
|
23
|
+
if (resParser.res.complete) {
|
|
24
|
+
resolvePromise === null || resolvePromise === void 0 ? void 0 : resolvePromise();
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
const waitForRes = new Promise((resolve, reject) => {
|
|
29
|
+
resolvePromise = resolve;
|
|
30
|
+
rejectPromise = reject;
|
|
31
|
+
});
|
|
32
|
+
const str = 'GET /myip.json HTTP/1.1\r\nHost: lumtest.com\r\n\r\n';
|
|
33
|
+
await session.write((0, tls_1.strToUint8Array)(str));
|
|
34
|
+
await waitForRes;
|
|
35
|
+
await session.close();
|
|
36
|
+
expect(resParser.res.statusCode).toBe(200);
|
|
37
|
+
const resBody = (0, tls_1.uint8ArrayToStr)(resParser.res.body);
|
|
38
|
+
const resJson = JSON.parse(resBody);
|
|
39
|
+
if (geoLocation === 'none') {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
expect(resJson.country).toBe(geoLocation.toUpperCase());
|
|
43
|
+
});
|
|
44
|
+
it('should gracefully fail an invalid geoLocation', async () => {
|
|
45
|
+
await expect((0, server_1.makeTcpTunnel)({
|
|
46
|
+
host: 'lumtest.com',
|
|
47
|
+
port: 80,
|
|
48
|
+
geoLocation: 'xz',
|
|
49
|
+
logger: utils_1.logger,
|
|
50
|
+
})).rejects.toMatchObject({
|
|
51
|
+
message: /failed with status code: 400/
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
it('should connect to restricted server', async () => {
|
|
55
|
+
const session = await (0, server_1.makeTcpTunnel)({
|
|
56
|
+
host: 'servicos.acesso.gov.br',
|
|
57
|
+
port: 80,
|
|
58
|
+
geoLocation: 'US',
|
|
59
|
+
logger: utils_1.logger,
|
|
60
|
+
});
|
|
61
|
+
await session.close();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC50Y3AtdHVubmVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3RzL3Rlc3QudGNwLXR1bm5lbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDhDQUF1RTtBQUN2RSx1Q0FBMEM7QUFDMUMscUNBQTBEO0FBRTFELE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUE7QUFFdkMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFNLENBQUMsQ0FBQTtBQUV2QixRQUFRLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtJQUUzQixFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxrQkFBa0IsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLG9EQUFvRCxFQUFFLEtBQUssRUFBQyxXQUFXLEVBQUUsRUFBRTtRQUNuSCxNQUFNLFNBQVMsR0FBRyxJQUFBLDhCQUFzQixHQUFFLENBQUE7UUFFMUMsSUFBSSxjQUF3QyxDQUFBO1FBQzVDLElBQUksYUFBaUQsQ0FBQTtRQUVyRCxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUEsc0JBQWEsRUFBQztZQUNuQyxJQUFJLEVBQUUsYUFBYTtZQUNuQixJQUFJLEVBQUUsRUFBRTtZQUNSLFdBQVcsRUFBRSxXQUFXLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVc7WUFDdEQsTUFBTSxFQUFOLGNBQU07WUFDTixPQUFPLENBQUMsR0FBRztnQkFDVixhQUFhLGFBQWIsYUFBYSx1QkFBYixhQUFhLENBQUcsR0FBRyxJQUFJLElBQUksS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQTtZQUNwRCxDQUFDO1lBQ0QsU0FBUyxDQUFDLElBQUk7Z0JBQ2IsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtnQkFDdkIsSUFBRyxTQUFTLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUMzQixjQUFjLGFBQWQsY0FBYyx1QkFBZCxjQUFjLEVBQUksQ0FBQTtnQkFDbkIsQ0FBQztZQUNGLENBQUM7U0FDRCxDQUFDLENBQUE7UUFFRixNQUFNLFVBQVUsR0FBRyxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUN4RCxjQUFjLEdBQUcsT0FBTyxDQUFBO1lBQ3hCLGFBQWEsR0FBRyxNQUFNLENBQUE7UUFDdkIsQ0FBQyxDQUFDLENBQUE7UUFFRixNQUFNLEdBQUcsR0FBRyxzREFBc0QsQ0FBQTtRQUNsRSxNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBQSxxQkFBZSxFQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDekMsTUFBTSxVQUFVLENBQUE7UUFFaEIsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDckIsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQzFDLE1BQU0sT0FBTyxHQUFHLElBQUEscUJBQWUsRUFBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ25ELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFbkMsSUFBRyxXQUFXLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDM0IsT0FBTTtRQUNQLENBQUM7UUFFRCxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FDM0IsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUN6QixDQUFBO0lBQ0YsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsK0NBQStDLEVBQUUsS0FBSyxJQUFHLEVBQUU7UUFDN0QsTUFBTSxNQUFNLENBQ1gsSUFBQSxzQkFBYSxFQUFDO1lBQ2IsSUFBSSxFQUFFLGFBQWE7WUFDbkIsSUFBSSxFQUFFLEVBQUU7WUFDUixXQUFXLEVBQUUsSUFBSTtZQUNqQixNQUFNLEVBQU4sY0FBTTtTQUNOLENBQUMsQ0FDRixDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUM7WUFDdkIsT0FBTyxFQUFFLDhCQUE4QjtTQUN2QyxDQUFDLENBQUE7SUFDSCxDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQyxxQ0FBcUMsRUFBRSxLQUFLLElBQUcsRUFBRTtRQUNuRCxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUEsc0JBQWEsRUFBQztZQUNuQyxJQUFJLEVBQUUsd0JBQXdCO1lBQzlCLElBQUksRUFBRSxFQUFFO1lBQ1IsV0FBVyxFQUFFLElBQUk7WUFDakIsTUFBTSxFQUFOLGNBQU07U0FDTixDQUFDLENBQUE7UUFFRixNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQTtJQUN0QixDQUFDLENBQUMsQ0FBQTtBQUNILENBQUMsQ0FBQyxDQUFBIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tls_1 = require("@reclaimprotocol/tls");
|
|
4
|
+
const utils_1 = require("src/utils");
|
|
5
|
+
const ZK_CIPHER_SUITES = [
|
|
6
|
+
'TLS_CHACHA20_POLY1305_SHA256',
|
|
7
|
+
'TLS_AES_128_GCM_SHA256',
|
|
8
|
+
'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384',
|
|
9
|
+
];
|
|
10
|
+
const ZK_ENGINES = [
|
|
11
|
+
'gnark',
|
|
12
|
+
'snarkJS'
|
|
13
|
+
];
|
|
14
|
+
jest.setTimeout(90000); // 90s
|
|
15
|
+
describe('ZK Tests', () => {
|
|
16
|
+
it('should correctly redact blocks', () => {
|
|
17
|
+
const vectors = [
|
|
18
|
+
{
|
|
19
|
+
input: [
|
|
20
|
+
'hell',
|
|
21
|
+
'o world'
|
|
22
|
+
],
|
|
23
|
+
output: [
|
|
24
|
+
'h***',
|
|
25
|
+
'* world'
|
|
26
|
+
],
|
|
27
|
+
redactions: [
|
|
28
|
+
{ fromIndex: 1, toIndex: 5 }
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
input: [
|
|
33
|
+
'hell',
|
|
34
|
+
'o world'
|
|
35
|
+
],
|
|
36
|
+
output: [
|
|
37
|
+
// first block is completely
|
|
38
|
+
// redacted, so it won't be included
|
|
39
|
+
'* world'
|
|
40
|
+
],
|
|
41
|
+
redactions: [
|
|
42
|
+
{ fromIndex: 0, toIndex: 5 }
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
input: [
|
|
47
|
+
'hello',
|
|
48
|
+
'how',
|
|
49
|
+
'do',
|
|
50
|
+
'you',
|
|
51
|
+
'do'
|
|
52
|
+
],
|
|
53
|
+
output: [
|
|
54
|
+
'he**o',
|
|
55
|
+
'd*',
|
|
56
|
+
'y*u',
|
|
57
|
+
'do'
|
|
58
|
+
],
|
|
59
|
+
redactions: [
|
|
60
|
+
{ fromIndex: 2, toIndex: 4 },
|
|
61
|
+
{ fromIndex: 5, toIndex: 8 },
|
|
62
|
+
{ fromIndex: 9, toIndex: 10 },
|
|
63
|
+
{ fromIndex: 11, toIndex: 12 }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
];
|
|
67
|
+
for (const { input, output, redactions } of vectors) {
|
|
68
|
+
const realOutput = (0, utils_1.getBlocksToReveal)(input.map(i => ({ plaintext: Buffer.from(i) })), () => redactions);
|
|
69
|
+
if (realOutput === 'all') {
|
|
70
|
+
fail('should not return "all"');
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
expect(realOutput).toHaveLength(output.length);
|
|
74
|
+
for (const [i, element] of output.entries()) {
|
|
75
|
+
expect((0, utils_1.uint8ArrayToStr)(realOutput[i].redactedPlaintext)).toEqual(element);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe.each(ZK_CIPHER_SUITES)('[%s] should generate ZK proof for some ciphertext', (cipherSuite) => {
|
|
81
|
+
describe.each(ZK_ENGINES)('[%s]', (zkEngine) => {
|
|
82
|
+
it(zkEngine + '-' + cipherSuite, async () => {
|
|
83
|
+
const alg = cipherSuite.includes('CHACHA20')
|
|
84
|
+
? 'CHACHA20-POLY1305'
|
|
85
|
+
: (cipherSuite.includes('AES_256_GCM')
|
|
86
|
+
? 'AES-256-GCM'
|
|
87
|
+
: 'AES-128-GCM');
|
|
88
|
+
const keylength = alg === 'AES-128-GCM' ? 16 : 32;
|
|
89
|
+
const key = Buffer.alloc(keylength, 0);
|
|
90
|
+
key[0] = 1;
|
|
91
|
+
key[3] = 4;
|
|
92
|
+
const { ivLength: fixedIvLength, } = tls_1.SUPPORTED_CIPHER_SUITE_MAP[cipherSuite];
|
|
93
|
+
const fixedIv = Buffer.alloc(fixedIvLength, 0);
|
|
94
|
+
fixedIv[0] = 1;
|
|
95
|
+
fixedIv[3] = 4;
|
|
96
|
+
const encKey = await tls_1.crypto.importKey(alg, key);
|
|
97
|
+
const vectors = [
|
|
98
|
+
{
|
|
99
|
+
plaintext: 'My cool API secret is "my name jeff". Please don\'t reveal it',
|
|
100
|
+
redactions: [
|
|
101
|
+
{ fromIndex: 23, toIndex: 35 }
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
plaintext: `lorem ipsum dolor sit amet, consectetur adipiscing elit,
|
|
106
|
+
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
|
107
|
+
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
|
|
108
|
+
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
|
|
109
|
+
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
|
|
110
|
+
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim
|
|
111
|
+
id est laborum`,
|
|
112
|
+
redactions: [
|
|
113
|
+
{ fromIndex: 5, toIndex: 15 },
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
];
|
|
117
|
+
const proofGenerator = await (0, utils_1.makeZkProofGenerator)({
|
|
118
|
+
logger: utils_1.logger,
|
|
119
|
+
cipherSuite,
|
|
120
|
+
zkEngine: zkEngine
|
|
121
|
+
});
|
|
122
|
+
for (const { plaintext, redactions } of vectors) {
|
|
123
|
+
const plaintextArr = Buffer.from(plaintext);
|
|
124
|
+
const redactedPlaintext = (0, utils_1.redactSlices)(plaintextArr, redactions);
|
|
125
|
+
// ensure redaction fn kinda works at least
|
|
126
|
+
expect(redactedPlaintext).not.toEqual(plaintextArr);
|
|
127
|
+
const { ciphertext, iv } = await (0, tls_1.encryptWrappedRecord)(plaintextArr, {
|
|
128
|
+
key: encKey,
|
|
129
|
+
iv: fixedIv,
|
|
130
|
+
recordNumber: 1234,
|
|
131
|
+
recordHeaderOpts: {
|
|
132
|
+
type: 'WRAPPED_RECORD'
|
|
133
|
+
},
|
|
134
|
+
cipherSuite,
|
|
135
|
+
version: cipherSuite.includes('ECDHE_')
|
|
136
|
+
? 'TLS1_2'
|
|
137
|
+
: 'TLS1_3',
|
|
138
|
+
});
|
|
139
|
+
const packet = {
|
|
140
|
+
type: 'ciphertext',
|
|
141
|
+
encKey,
|
|
142
|
+
iv,
|
|
143
|
+
recordNumber: 1234,
|
|
144
|
+
plaintext: plaintextArr,
|
|
145
|
+
ciphertext,
|
|
146
|
+
fixedIv: fixedIv,
|
|
147
|
+
data: ciphertext
|
|
148
|
+
};
|
|
149
|
+
let proofs;
|
|
150
|
+
await proofGenerator.addPacketToProve(packet, {
|
|
151
|
+
type: 'zk',
|
|
152
|
+
redactedPlaintext,
|
|
153
|
+
}, p => proofs = p);
|
|
154
|
+
await proofGenerator.generateProofs();
|
|
155
|
+
const x = await (0, utils_1.verifyZkPacket)({
|
|
156
|
+
ciphertext,
|
|
157
|
+
zkReveal: { proofs: proofs },
|
|
158
|
+
logger: utils_1.logger,
|
|
159
|
+
cipherSuite,
|
|
160
|
+
zkEngine: zkEngine,
|
|
161
|
+
recordNumber: 1234,
|
|
162
|
+
iv: fixedIv
|
|
163
|
+
});
|
|
164
|
+
expect(redactedPlaintext).toEqual(x.redactedPlaintext);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC56ay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0cy90ZXN0LnprLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsOENBQTRHO0FBRzVHLHFDQU9rQjtBQUVsQixNQUFNLGdCQUFnQixHQUFrQjtJQUN2Qyw4QkFBOEI7SUFDOUIsd0JBQXdCO0lBQ3hCLHlDQUF5QztDQUN6QyxDQUFBO0FBRUQsTUFBTSxVQUFVLEdBQWU7SUFDOUIsT0FBTztJQUNQLFNBQVM7Q0FDVCxDQUFBO0FBRUQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFNLENBQUMsQ0FBQSxDQUFDLE1BQU07QUFFOUIsUUFBUSxDQUFDLFVBQVUsRUFBRSxHQUFHLEVBQUU7SUFFekIsRUFBRSxDQUFDLGdDQUFnQyxFQUFFLEdBQUcsRUFBRTtRQUN6QyxNQUFNLE9BQU8sR0FBRztZQUNmO2dCQUNDLEtBQUssRUFBRTtvQkFDTixNQUFNO29CQUNOLFNBQVM7aUJBQ1Q7Z0JBQ0QsTUFBTSxFQUFFO29CQUNQLE1BQU07b0JBQ04sU0FBUztpQkFDVDtnQkFDRCxVQUFVLEVBQUU7b0JBQ1gsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUU7aUJBQzVCO2FBQ0Q7WUFDRDtnQkFDQyxLQUFLLEVBQUU7b0JBQ04sTUFBTTtvQkFDTixTQUFTO2lCQUNUO2dCQUNELE1BQU0sRUFBRTtvQkFDUCw0QkFBNEI7b0JBQzVCLG9DQUFvQztvQkFDcEMsU0FBUztpQkFDVDtnQkFDRCxVQUFVLEVBQUU7b0JBQ1gsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUU7aUJBQzVCO2FBQ0Q7WUFDRDtnQkFDQyxLQUFLLEVBQUU7b0JBQ04sT0FBTztvQkFDUCxLQUFLO29CQUNMLElBQUk7b0JBQ0osS0FBSztvQkFDTCxJQUFJO2lCQUNKO2dCQUNELE1BQU0sRUFBRTtvQkFDUCxPQUFPO29CQUNQLElBQUk7b0JBQ0osS0FB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
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function delay(ms: number): Promise<unknown>;
|
|
2
|
+
export declare function randomPrivateKey(): string;
|
|
3
|
+
export declare function getRandomPort(): number;
|
|
4
|
+
/**
|
|
5
|
+
* Verifies that no direct reveal accidentally leaked
|
|
6
|
+
* the key. This is done by checking that no other
|
|
7
|
+
* application data packets were sent with the same key
|
|
8
|
+
*
|
|
9
|
+
* Uses the spy on preparePacketsForReveal to get the
|
|
10
|
+
* tls transcript and reveals map that was used.
|
|
11
|
+
*/
|
|
12
|
+
export declare function verifyNoDirectRevealLeaks(): void;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.delay = delay;
|
|
4
|
+
exports.randomPrivateKey = randomPrivateKey;
|
|
5
|
+
exports.getRandomPort = getRandomPort;
|
|
6
|
+
exports.verifyNoDirectRevealLeaks = verifyNoDirectRevealLeaks;
|
|
7
|
+
const crypto_1 = require("crypto");
|
|
8
|
+
const mocks_1 = require("src/tests/mocks");
|
|
9
|
+
function delay(ms) {
|
|
10
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11
|
+
}
|
|
12
|
+
function randomPrivateKey() {
|
|
13
|
+
return '0x' + (0, crypto_1.randomBytes)(32).toString('hex');
|
|
14
|
+
}
|
|
15
|
+
function getRandomPort() {
|
|
16
|
+
return Math.floor(Math.random() * 5000 + 5000);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Verifies that no direct reveal accidentally leaked
|
|
20
|
+
* the key. This is done by checking that no other
|
|
21
|
+
* application data packets were sent with the same key
|
|
22
|
+
*
|
|
23
|
+
* Uses the spy on preparePacketsForReveal to get the
|
|
24
|
+
* tls transcript and reveals map that was used.
|
|
25
|
+
*/
|
|
26
|
+
function verifyNoDirectRevealLeaks() {
|
|
27
|
+
if (!mocks_1.SPY_PREPARER.mock.calls.length) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const [tlsTranscript, revealsMap] = mocks_1.SPY_PREPARER.mock.calls[0];
|
|
31
|
+
for (const [packet, reveal] of revealsMap.entries()) {
|
|
32
|
+
if (reveal.type !== 'complete') {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (packet.type === 'plaintext') {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// find any other packets with the same key
|
|
39
|
+
// that do not have a reveal & were application data.
|
|
40
|
+
// If we find any, it means we've leaked the key
|
|
41
|
+
const otherPacketsWKey = tlsTranscript
|
|
42
|
+
.filter(({ message }) => (message.type === 'ciphertext'
|
|
43
|
+
&& !revealsMap.get(message)
|
|
44
|
+
&& message.encKey === packet.encKey
|
|
45
|
+
&& message.contentType === 'APPLICATION_DATA'));
|
|
46
|
+
expect(otherPacketsWKey).toHaveLength(0);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdHMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFHQSxzQkFFQztBQUVELDRDQUVDO0FBRUQsc0NBRUM7QUFVRCw4REEyQkM7QUFsREQsbUNBQW9DO0FBQ3BDLDJDQUE4QztBQUU5QyxTQUFnQixLQUFLLENBQUMsRUFBVTtJQUMvQixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUE7QUFDekQsQ0FBQztBQUVELFNBQWdCLGdCQUFnQjtJQUMvQixPQUFPLElBQUksR0FBRyxJQUFBLG9CQUFXLEVBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQzlDLENBQUM7QUFFRCxTQUFnQixhQUFhO0lBQzVCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFBO0FBQy9DLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsU0FBZ0IseUJBQXlCO0lBQ3hDLElBQUcsQ0FBQyxvQkFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDcEMsT0FBTTtJQUNQLENBQUM7SUFFRCxNQUFNLENBQUMsYUFBYSxFQUFFLFVBQVUsQ0FBQyxHQUFHLG9CQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUM5RCxLQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7UUFDcEQsSUFBRyxNQUFNLENBQUMsSUFBSSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQy9CLFNBQVE7UUFDVCxDQUFDO1FBRUQsSUFBRyxNQUFNLENBQUMsSUFBSSxLQUFLLFdBQVcsRUFBRSxDQUFDO1lBQ2hDLFNBQVE7UUFDVCxDQUFDO1FBRUQsMkNBQTJDO1FBQzNDLHFEQUFxRDtRQUNyRCxnREFBZ0Q7UUFDaEQsTUFBTSxnQkFBZ0IsR0FBRyxhQUFhO2FBQ3BDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQ3hCLE9BQU8sQ0FBQyxJQUFJLEtBQUssWUFBWTtlQUMxQixDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDO2VBQ3hCLE9BQU8sQ0FBQyxNQUFNLEtBQUssTUFBTSxDQUFDLE1BQU07ZUFDaEMsT0FBTyxDQUFDLFdBQVcsS0FBSyxrQkFBa0IsQ0FDN0MsQ0FBQyxDQUFBO1FBQ0gsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3pDLENBQUM7QUFDRixDQUFDIn0=
|