-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathchunked.example.ts
More file actions
86 lines (77 loc) · 3.23 KB
/
Copy pathchunked.example.ts
File metadata and controls
86 lines (77 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Copyright (c) 2024
// Licensed under the MIT license
import {
AEAD_AES_128_GCM,
CipherSuite,
KDF_HKDF_SHA256,
KEM_DHKEM_X25519_HKDF_SHA256,
} from "hpke";
import {
AeadId,
ChunkedOHTTPClient,
ChunkedOHTTPServer,
KdfId,
KeyConfig,
} from "../src/index.js";
// Follows draft-ietf-ohai-chunked-ohttp-08
async function setup() {
const suite = new CipherSuite(
KEM_DHKEM_X25519_HKDF_SHA256,
KDF_HKDF_SHA256,
AEAD_AES_128_GCM,
);
const keyConfig = await KeyConfig.generate(suite, 0x01, [
{ kdfId: KdfId.HKDF_SHA256, aeadId: AeadId.AES_128_GCM },
]);
// Use custom chunk size for demonstration
const gateway = new ChunkedOHTTPServer([keyConfig], { maxChunkSize: 64 });
const client = new ChunkedOHTTPClient(suite, keyConfig, { maxChunkSize: 64 });
return { gateway, client };
}
export async function chunkedOHTTP(): Promise<boolean> {
// Protocol Setup
//
// [ Everybody ] agree to use Chunked Oblivious HTTP
const { gateway, client } = await setup();
// Online Protocol (draft-08 Figure 1)
//
// Client Relay Gateway
// | | |
// | Relay Request | |
// | [+ Encapsulated Request | |
// | (chunk 1 ... N) ] | |
const request = new TextEncoder().encode(
"POST /upload HTTP/1.1\r\n\r\n" + "X".repeat(200), // Large enough to chunk
);
const { encapsulatedRequest, createResponseContext } = await client.encapsulate(request);
// +---------------------------->| Gateway Request |
// | | [+ Encapsulated Request |
// | | (chunk 1 ... N) ] |
// | +---------------------------->|
// | | |
const { request: decryptedRequest, createResponseContext: serverCreateResponse } =
await gateway.decapsulate(encapsulatedRequest);
// | | |
// | | Gateway Response |
// | | [+ Encapsulated Response |
// | | (chunk 1 ... M) ] |
const response = new TextEncoder().encode(
"HTTP/1.1 200 OK\r\n\r\n" + "Y".repeat(150), // Large enough to chunk
);
const responseCtx = await serverCreateResponse();
const encapsulatedResponse = await gateway.encapsulateResponse(responseCtx, response);
// | Relay Response |<----------------------------+
// | [+ Encapsulated Response | |
// | (chunk 1 ... M) ] | |
// |<----------------------------+ |
// | | |
const decryptedResponse = await client.decapsulateResponse(
createResponseContext,
encapsulatedResponse,
);
const requestMatch =
new TextDecoder().decode(decryptedRequest) === new TextDecoder().decode(request);
const responseMatch =
new TextDecoder().decode(decryptedResponse) === new TextDecoder().decode(response);
return requestMatch && responseMatch;
}