tunnelfetch 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -28
- package/README.zh-CN.md +54 -11
- package/package.json +5 -1
- package/src/client.js +27 -2
- package/src/profile/chrome.js +45 -0
- package/src/profile/vendor/chacha20poly1305.js +65 -0
- package/src/profile/vendor/mlkem768.js +67 -0
- package/src/profiles.js +47 -13
- package/src/tls/aead.js +51 -16
- package/src/tls/connect.js +42 -7
- package/src/tls/constants.js +60 -6
- package/src/tls/handshake-messages.js +18 -5
- package/src/tls/handshake.js +1 -1
- package/src/tls/hybrid.js +166 -0
- package/src/tls/record.js +24 -3
- package/src/warmup-fixture.js +46 -45
- package/types/client.d.ts +28 -0
- package/types/profile/chrome.d.ts +16 -0
- package/types/profile/vendor/chacha20poly1305.d.ts +7 -0
- package/types/profile/vendor/mlkem768.d.ts +23 -0
- package/types/profiles.d.ts +6 -2
- package/types/tls/aead.d.ts +17 -1
- package/types/tls/connect.d.ts +30 -4
- package/types/tls/constants.d.ts +31 -3
- package/types/tls/handshake-messages.d.ts +8 -4
- package/types/tls/hybrid.d.ts +63 -0
- package/types/tls/record.d.ts +23 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// ML-KEM-768 (FIPS 203, final — NOT round-3 Kyber) — mlkem-native v1.2.0 single-compilation-
|
|
2
|
+
// unit build, compiled UNMODIFIED to freestanding wasm32 with wasi-sdk 25 / LLVM 19.
|
|
3
|
+
// Zero wasm imports; randomness is injected by the caller (or fetched from WebCrypto here).
|
|
4
|
+
// Sources and build: wasmcrypto/c/mlkem768_shim.c, wasmcrypto/build.sh.
|
|
5
|
+
// AUTO-GENERATED by wasmcrypto/gen-js.mjs — edit that, not this.
|
|
6
|
+
// wasm sha256[0..12): e17c38843d1e raw 31353 bytes
|
|
7
|
+
|
|
8
|
+
const B64 = "AGFzbQEAAAABPwlgAAF/YAJ/fwBgAX8AYAR/f39/AGADf39/AX9gAn9/AX9gBX9/f39/AGAGf39/f39/AGAJf39/f39/f39/AAMcGwQFAAAAAAAAAAAAAAAABgEHAggCAQMCAwECAQUDAQADBggBfwFBgLEICweMAQ0GbWVtb3J5AgAIbWtfY29pbnMAAgZta19tc2cAAwVta19wawAEBW1rX3NrAAUFbWtfY3QABgVta19zcwAHC21rX3BrX2J5dGVzAAgLbWtfc2tfYnl0ZXMACQtta19jdF9ieXRlcwAKCW1rX2tleWdlbgALCW1rX2VuY2FwcwAMCW1rX2RlY2FwcwANCtntARvGAQEDfwJAIAJFDQACQCACQQdxIgVFBEAgACEDIAIhBAwBCyACQXhxIQQgACEDA0AgAyABLQAAOgAAIANBAWohAyABQQFqIQEgBUEBayIFDQALCyACQQhJDQADQCADIAEtAAA6AAAgAyABLQABOgABIAMgAS0AAjoAAiADIAEtAAM6AAMgAyABLQAEOgAEIAMgAS0ABToABSADIAEtAAY6AAYgAyABLQAHOgAHIANBCGohAyABQQhqIQEgBEEIayIEDQALCyAAC5MBAQN/AkAgAUUNACAAIQIgASEDIAFBB3EiBARAIAFBeHEhAwNAIAJBADoAACACQQFqIQIgBEEBayIEDQALCyABQQhJDQADQCACQQA6AAcgAkEAOgAGIAJBADoABSACQQA6AAQgAkEAOgADIAJBADoAAiACQQA6AAEgAkEAOgAAIAJBCGohAiADQQhrIgMNAAsLIAALBQBBwAsLBQBBgAwLBQBBoAwLBQBBwBULBQBBoCgLBQBB4DALBQBBoAkLBQBB4BILBQBBwAgL3R4CDn8DfiMAQdABayIGJAAjACIAIABBgM8Aa0FgcSIAJAAgAEEDOgCgTiAAQcALKQAANwOATiAAQcgLKQAANwOITiAAQdALKQAANwOQTiAAQdgLKQAANwOYTiAAQZAqakG4ARABIQIgACAALQCATjoAgCogACAAKACBTjYAgSogACAAKQCFTjcAhSogACAAKQCNTjcAjSogACAAKACVTjYAlSogACAALQCZKiAALQCZTnM6AJkqIAAgAC0AmiogAC0Amk5zOgCaKiAAIAAtAJsqIAAtAJtOczoAmyogACAALQCcKiAA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AHM6AAAgAUGLAWoiASABLQAAIAJBmwNqLQAAczoAACAAQQRqIgANAAsgAxARQfh+IQADQCAAIANqIgFBiAFqIgIgAi0AACAAQaAMaiICQaAEai0AAHM6AAAgAUGJAWoiBCAELQAAIAJBoQRqLQAAczoAACABQYoBaiIEIAQtAAAgAkGiBGotAABzOgAAIAFBiwFqIgEgAS0AACACQaMEai0AAHM6AAAgAEEEaiIADQALIAMQEUH4fiEAA0AgACADaiIBQYgBaiICIAItAAAgAEGgDGoiAkGoBWotAABzOgAAIAFBiQFqIgQgBC0AACACQakFai0AAHM6AAAgAUGKAWoiBCAELQAAIAJBqgVqLQAAczoAACABQYsBaiIBIAEtAAAgAkGrBWotAABzOgAAIABBBGoiAA0ACyADEBFB+H4hAANAIAAgA2oiAUGIAWoiAiACLQAAIABBoAxqIgJBsAZqLQAAczoAACABQYkBaiIEIAQtAAAgAkGxBmotAABzOgAAIAFBigFqIgQgBC0AACACQbIGai0AAHM6AAAgAUGLAWoiASABLQAAIAJBswZqLQAAczoAACAAQQRqIgANAAsgAxARQfh+IQADQCAAIANqIgFBiAFqIgIgAi0AACAAQaAMaiICQbgHai0AAHM6AAAgAUGJAWoiBCAELQAAIAJBuQdqLQAAczoAACABQYoBaiIEIAQtAAAgAkG6B2otAABzOgAAIAFBiwFqIgEgAS0AACACQbsHai0AAHM6AAAgAEEEaiIADQALIAMQEUH4fiEAA0AgACADaiIBQYgBaiICIAItAAAgAEGgDGoiAkHACGotAABzOgAAIAFBiQFqIgQgBC0AACACQcEIai0AAHM6AAAgAUGKAWoiBCAELQAAIAJBwghqLQAAczoAACABQYsBaiIBIAEtAAAgAkHDCGotAABzOgAAIABBBGoiAA0ACyADEBFBoH8hAANAIAAgA2oiAUHgAGoiAiACLQAAIABBoAxqIgJBoAlqLQAAczoAACABQeEAaiIEIAQtAAAgAkGhCWotAABzOgAAIAFB4gBqIgQgBC0AACACQaIJai0AAHM6AAAgAUHjAGoiASABLQAAIAJBowlqLQAAczoAACAAQQRqIgANAAsgAyADLQBgQQZzOgBgIAMgAy0AhwFBgAFzOgCHASADEBFB+CcgA0EYaikD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IQMDQCACQZABaiIBIANqIgVB4ABqIgQgBC0AACADQaAMaiIEQaAJai0AAHM6AAAgBUHhAGoiBiAGLQAAIARBoQlqLQAAczoAACAFQeIAaiIGIAYtAAAgBEGiCWotAABzOgAAIAVB4wBqIgUgBS0AACAEQaMJai0AAHM6AAAgA0EEaiIDDQALIAIgAi0A8AFBBnM6APABIAIgAi0AlwJBgAFzOgCXAiABEBEgAEEYaiACQagBaikDADcDACAAQRBqIAJBoAFqKQMANwMAIABBCGogAikDmAE3AwAgACACKQOQATcDACABQcgBEAEaIAFByAEQARpBQCEDA0AgAkGQAWoiBSADaiIAQUBrIgEgAS0AACACQUBrIgQgA2oiAUFAay0AAHM6AAAgAEHBAGoiBiAGLQAAIAFBwQBqLQAAczoAACAAQcIAaiIGIAYtAAAgAUHCAGotAABzOgAAIABBwwBqIgAgAC0AACABQcMAai0AAHM6AAAgA0EEaiIDDQALIAIgAi0A0AFBBnM6ANABIAIgAi0A1wFBgAFzOgDXASAFEBEgAkE4aiACQcgBaikDADcDACACQTBqIAJBwAFqKQMANwMAIAJBKGogAkG4AWopAwA3AwAgAkEgaiIDIAJBsAFqKQMANwMAIAIgAkGoAWopAwA3AxggAiACQaABaikDADcDECACIAIpA5gBNwMIIAIgAikDkAE3AwAgBUHIARABGkGgKCAEQaAMIAMQF0H4MCACKQMYNwAAQfAwIAIpAxA3AABB6DAgAikDCDcAAEHgMCACKQMANwAAQQAhAwsgAkE4akIANwMAIAJBMGpCADcDACACQShqQgA3AwAgAkEgakIANwMAIAJCADcDGCACQgA3AxAgAkIANwMIIAJCADcDACACQfgAakIANwMAIAJB8ABqQgA3AwAgAkHoAGpCADcDACACQeAAakIANwMAIAJCADcDWCACQgA3A1AgAkIANwNIIAJCADcDQCQAIAML8y8BJn8jACIAIABBwAtrQWBxIgkkAEF/IQUjACIAIABBgAJrQWBxIgAkACAAQTBqQcgBEAEaQfh+IQEDQCAAQTBqIgYgAWoiA0GIAWoiAiACLQAAIAFBwBVqIgJBiApqLQAAczoAACADQYkBaiIEIAQtAAAgAkGJCmotAABzOgAAIANBigFqIgQgBC0AACACQYoKai0AAHM6AAAgA0GLAWoiAyADLQAAIAJBiwpqLQAAczoAACABQQRqIgENAAsgBhARQfh+IQEDQCAAQTBqIgYgAWoiA0GIAWoiAiACLQAAIAFBwBVqIgJBkAtqLQAAczoAACADQYkBaiIEIAQtAAAgAkGRC2otAABzOgAAIANBigFqIgQgBC0AACACQZILai0AAHM6AAAgA0GLAWoiAyADLQAAIAJBkwtqLQAAczoAACABQQRqIgENAAsgBhARQfh+IQEDQCAAQTBqIgYgAWoiA0GIAWoiAiACLQAAIAFBwBVqIgJBmAxqLQAAczoAACADQYkBaiIEIAQtAAAgAkGZDGotAABzOgAAIANBigFqIgQgBC0AACACQZoMai0AAHM6AAAgA0GLAWoiAyADLQAAIAJBmwxqLQAAczoAACABQQRqIgENAAsgBhARQfh+IQEDQCAAQTBqIgYgAWoiA0GIAWoiAiACLQAAIAFBwBVqIgJBoA1qLQAAczoAACADQYkBaiIEIAQtAAAgAkGhDWotAABzOgAAIANBigFqIgQgBC0AACACQaINai0AAHM6AAAgA0GLAWoiAyADLQAAIAJBow1qLQAAczoAACABQQRqIgENAAsgBhARQfh+IQEDQCAAQTBqIgYgAWoiA0GIAWoiAiACLQAAIAFBwBVqIgJBqA5qLQAAczoAACADQYkBaiIEIAQtAAAgAkGpDmotAABzOgAAIANBigFqIgQgBC0AACACQaoOai0AAHM6AAAgA0GLAWoiAyADLQAAIAJBqw5qLQAAczoAACABQQRqIgENAAsgBhARQfh+IQEDQCAAQTBqIgYgAWoiA0GIAWoiAiACLQAAIAFBwBVqIgJBsA9qLQAAczoAACADQYkBaiIEIAQtAAAgAkGxD2otAABzOgAAIANBigFqIgQgBC0AACACQbIPai0AAHM6AAAgA0GLAWoiAyADLQAAIAJBsw9qLQAAczoAACABQQRqIgENAAsgBhARQfh+IQEDQCAAQTBqIgYgAWoiA0GIAWoiAiACLQAAIAFBwBVqIgJBuBBqLQAAczoAACADQYkBaiIEIAQtAAAgAkG5EGotAABzOgAAIANBigFqIgQgBC0AACACQboQai0AAHM6AAAgA0GLAWoiAyADLQAAIAJBuxBqLQAAczoAACABQQRqIgENAAsgBhARQfh+IQEDQCAAQTBqIgYgAWoiA0GIAWoiAiACLQAAIAFBwBVqIgJBwBFqLQAAczoAACADQYkBaiIEIAQtAAAgAkHBEWotAABzOgAAIANBigFqIgQgBC0AACACQcIRai0AAHM6AAAgA0GLAWoiAyADLQAAIAJBwxFqLQAAczoAACABQQRqIgENAAsgBhARQaB/IQEDQCAAQTBqIgYgAWoiA0HgAGoiAiACLQAAIAFBwBVqIgJBoBJqLQAAczoAACADQeEAaiIEIAQtAAAgAkGhEmotAABzOgAAIANB4gBqIgQgBC0AACACQaISai0AAHM6AAAgA0HjAGoiAyADLQAAIAJBoxJqLQAAczoAACABQQRqIgENAAsgACAALQCQAUEGczoAkAEgACAALQC3AUGAAXM6ALcBIAYQESAAIABByABqKQMANwMYIAAgAEFAaykDADcDECAAIAApAzg3AwggACAAKQMwNwMAIAZByAEQARpBACAALQAfQf8nLQAAcyIBIAAtAB5B/ictAABzIgMgAC0AHUH9Jy0AAHMiAiAALQAcQfwnLQAAcyIGIAAtABtB+yctAABzIgQgAC0AGkH6Jy0AAHMiCCAALQAZQfknLQAAcyILIAAtABhB+CctAABzIgogAC0AF0H3Jy0AAHMiDSAALQAWQfYnLQAAcyIOIAAtABVB9SctAABzIg8gAC0AFEH0Jy0AAHMiECAALQATQfMnLQAAcyIRIAAtABJB8ictAABzIhIgAC0AEUHxJy0AAHMiEyAALQAQQfAnLQAAcyIUIAAtAA9B7yctAABzIhUgAC0ADkHuJy0AAHMiFiAALQANQe0nLQAAcyIXIAAtAAxB7CctAABzIhggAC0AC0HrJy0AAHMiGSAALQAKQeonLQAAcyIaIAAtAAlB6SctAABzIhsgAC0ACEHoJy0AAHMiHCAALQAHQecnLQAAcyIdIAAtAAZB5ictAABzIh4gAC0ABUHlJy0AAHMiHyAALQAEQeQnLQAAcyIgIAAtAANB4yctAABzIiEgAC0AAkHiJy0AAHMiIiAALQABQeEnLQAAcyIjIAAtAABB4CctAABzIiRycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJyayElIABCADcDACAAQgA3AwggAEIANwMQIABCADcDGCQAIAEgAyACIAYgBCAIIAsgCiANIA4gDyAQIBEgEiATIBQgFSAWIBcgGCAZIBogGyAcIB0gHiAfICAgISAiICMgJHNzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3MiACAlQRB2c0H/AXEgAEH/AXFGBEAgCUGgCWohA0EAIQBBACEGIwAiASABQYAma0FgcSIFJAAgBUGAGmoiByEBA0AgAEGgKGoiAi0AACEKIAJBAWotAAAhBCACQQJqLQAAIQggAUEGaiACQQRqLQAAQQJ0IAJBA2otAAAiAkEGdnJBgRpsQYAEakEKdjsBACABQQRqIAJBBHRB8AdxIAhBBHZyQYEabEGABGpBCnY7AQAgAUECaiAIQQZ0QcAHcSAEQQJ2ckGBGmxBgARqQQp2OwEAIAEgCiAEQQh0QYAGcXJBgRpsQYAEakEKdjsBACABQQhqIQEgAEEFaiIAQcACRw0ACyAHQYYEaiEBQQAhAANAIABBoChqIgJBwAJqLQAAIQogAkHBAmotAAAhBCACQcICai0AACEIIAEgAkHEAmotAABBAnQgAkHDAmotAAAiAkEGdnJBgRpsQYAEakEKdjsBACABQQJrIAJBBHRB8AdxIAhBBHZyQYEabEGABGpBCnY7AQAgAUEEayAIQQZ0QcAHcSAEQQJ2ckGBGmxBgARqQQp2OwEAIAFBBmsgCiAEQQh0QYAGcXJBgRpsQYAEakEKdjsBACABQQhqIQEgAEEFaiIAQcACRw0ACyAHQYYIaiEBQQAhAANAIABBoChqIgJBgAVqLQAAIQggAkGBBWotAAAhByACQYIFai0AACEEIAEgAkGEBWotAABBAnQgAkGDBWotAAAiAkEGdnJBgRpsQYAEakEKdjsBACABQQJrIAJBBHRB8AdxIARBBHZyQYEabEGABGpBCnY7AQAgAUEEayAEQQZ0QcAHcSAHQQJ2ckGBGmxBgARqQQp2OwEAIAFBBmsgCCAHQQh0QYAGcXJBgRpsQYAEakEKdjsBACABQQhqIQEgAEEFaiIAQcACRw0AC0HgLyEAA0AgBUGACmogBmoiAUECaiAALQAAIgJBBHZBgRpsQQhqQQR2OwEAIAEgAkEPcUGBGmxBCGpBBHY7AQAgAEEBaiEAIAZBBGoiBkGABEcNAAsgBUGADmoiAUHAFRAYIAVBgBpqIgAQEyAFQYAeahATIAVBgCJqEBMgBSAAEBQgBUGABmoiAiABIAAgBRAVIAIQGUGAfCEAA0AgBUGACmogAGoiAUGABGoiAiACLwEAIAVBgAZqIABqIgJBgARqLwEAazsBACABQYIEaiIGIAYvAQAgAkGCBGovAQBrOwEAIAFBhARqIgYgBi8BACACQYQEai8BAGs7AQAgAUGGBGoiASABLwEAIAJBhgRqLwEAazsBACAAQQhqIgANAAtBACEAA0BBACAFQYAKaiICIABqIgYuAQAiAUG/nQFsQYCAgBBqQRp1Qf9lbCABaiIBwUEQdmshByAGIAFBgRpqIAFzIAdBEHZxIAFzOwEAIABBAmoiAEGABEcNAAtBACEBA0AgA0EAOgAAIAMgASACaiIALgEAQbjfzgBsQYCAgIAEakEfdiIGOgAAIAMgAEECai4BAEG4384AbEGAgICABGpBHnZBAnEgBnIiBjoAACADIAYgAEEEai4BAEG4384AbEGAgICABGpBHXZBBHFyIgY6AAAgAyAGIABBBmouAQBBuN/OAGxBgICAgARqQRx2QQhxciIGOgAAIAMgBiAAQQhqLgEAQbjfzgBsQYCAgIAEakEbdkEQcXIiBjoAACADIAYgAEEKai4BAEG4384AbEGAgICABGpBGnZBIHFyIgY6AAAgAyAGIABBDGouAQBBuN/OAGxBgICAgARqQRl2QcAAcXIiBjoAACADIAYgAEEOai4BAEG4384AbEGAgICABGpBGHZBgAFxcjoAACADQQFqIQMgAUEQaiIBQYAERw0ACyAFQYAGEAEiAEGABmpBgAQQARogAEGACmpBgAQQARogAEGADmpBgAwQARogAEGAGmpBgAwQARokACAJQdgJakH4JykAADcDACAJQdAJakHwJykAADcDACAJQcgJakHoJykAADcDACAJQeAnKQAANwPACSAJQcgBEAEhAEFAIQEDQCAAIAFqIgVBQGsiAyADLQAAIABBoAlqIAFqIgNBQGstAABzOgAAIAVBwQBqIgIgAi0AACADQcEAai0AAHM6AAAgBUHCAGoiAiACLQAAIANBwgBqLQAAczoAACAFQcMAaiIFIAUtAAAgA0HDAGotAABzOgAAIAFBBGoiAQ0ACyAAIAAtAEBBBnM6AEAgACAALQBHQYABczoARyAAEBEgAEGYCWogAEE4aikDADcDACAAQZAJaiAAQTBqKQMANwMAIABBiAlqIABB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";
|
|
9
|
+
|
|
10
|
+
function fromBase64(s) {
|
|
11
|
+
const bin = atob(s);
|
|
12
|
+
const u = new Uint8Array(bin.length);
|
|
13
|
+
for (let i = 0; i < u.length; i++) u[i] = bin.charCodeAt(i);
|
|
14
|
+
return u;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Module scope: on workerd this runs at isolate startup, which is not billed as request CPU.
|
|
18
|
+
// SYNCHRONOUS compile+instantiate, deliberately: the async forms (WebAssembly.compile /
|
|
19
|
+
// .instantiate) return promises that do not settle during workerd's startup evaluation, and
|
|
20
|
+
// the deploy is rejected with error 10021 "Top-level await in module is unsettled" — measured,
|
|
21
|
+
// not assumed. The module has zero imports; it cannot touch anything outside its own memory.
|
|
22
|
+
const _instance = new WebAssembly.Instance(new WebAssembly.Module(fromBase64(B64)), {});
|
|
23
|
+
const x = _instance.exports;
|
|
24
|
+
|
|
25
|
+
export const buildId = "e17c38843d1e";
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
const COINS = x.mk_coins(), MSGBUF = x.mk_msg();
|
|
29
|
+
const PK = x.mk_pk(), SK = x.mk_sk(), CT = x.mk_ct(), SS = x.mk_ss();
|
|
30
|
+
const PK_B = x.mk_pk_bytes(), SK_B = x.mk_sk_bytes(), CT_B = x.mk_ct_bytes();
|
|
31
|
+
let mem = new Uint8Array(x.memory.buffer);
|
|
32
|
+
const view = () => (mem.buffer === x.memory.buffer ? mem : (mem = new Uint8Array(x.memory.buffer)));
|
|
33
|
+
|
|
34
|
+
export const mlkem768 = {
|
|
35
|
+
publicKeyBytes: PK_B, secretKeyBytes: SK_B, cipherTextBytes: CT_B, sharedSecretBytes: 32,
|
|
36
|
+
/** keygen(seed?) — seed is d||z (64 bytes) for ML-KEM.KeyGen_internal; omitted = fresh CSPRNG */
|
|
37
|
+
keygen(seed) {
|
|
38
|
+
if (seed === undefined) crypto.getRandomValues((seed = new Uint8Array(64)));
|
|
39
|
+
if (seed.length !== 64) throw new RangeError('seed must be 64 bytes (d||z)');
|
|
40
|
+
const m = view();
|
|
41
|
+
m.set(seed, COINS);
|
|
42
|
+
if (x.mk_keygen() !== 0) throw new Error('mlkem768: keygen failed');
|
|
43
|
+
return { publicKey: m.slice(PK, PK + PK_B), secretKey: m.slice(SK, SK + SK_B) };
|
|
44
|
+
},
|
|
45
|
+
/** encapsulate(publicKey, msg?) — msg is m (32 bytes) for ML-KEM.Encaps_internal */
|
|
46
|
+
encapsulate(publicKey, msg) {
|
|
47
|
+
if (publicKey.length !== PK_B) throw new RangeError('bad public key length');
|
|
48
|
+
if (msg === undefined) crypto.getRandomValues((msg = new Uint8Array(32)));
|
|
49
|
+
if (msg.length !== 32) throw new RangeError('msg must be 32 bytes');
|
|
50
|
+
const m = view();
|
|
51
|
+
m.set(publicKey, PK);
|
|
52
|
+
m.set(msg, MSGBUF);
|
|
53
|
+
if (x.mk_encaps() !== 0) throw new Error('mlkem768: invalid public key (FIPS 203 7.2 modulus check)');
|
|
54
|
+
return { cipherText: m.slice(CT, CT + CT_B), sharedSecret: m.slice(SS, SS + 32) };
|
|
55
|
+
},
|
|
56
|
+
/** decapsulate(cipherText, secretKey) -> sharedSecret (implicit rejection per FIPS 203) */
|
|
57
|
+
decapsulate(cipherText, secretKey) {
|
|
58
|
+
if (cipherText.length !== CT_B) throw new RangeError('bad ciphertext length');
|
|
59
|
+
if (secretKey.length !== SK_B) throw new RangeError('bad secret key length');
|
|
60
|
+
const m = view();
|
|
61
|
+
m.set(cipherText, CT);
|
|
62
|
+
m.set(secretKey, SK);
|
|
63
|
+
if (x.mk_decaps() !== 0) throw new Error('mlkem768: invalid secret key (FIPS 203 7.3 hash check)');
|
|
64
|
+
return m.slice(SS, SS + 32);
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
package/src/profiles.js
CHANGED
|
@@ -69,28 +69,51 @@ export const curl = Object.freeze({
|
|
|
69
69
|
* `applyProfile` refuses both cases with a message naming what is missing.
|
|
70
70
|
*/
|
|
71
71
|
export const chrome = Object.freeze({
|
|
72
|
-
name: '
|
|
72
|
+
name: 'chrome/150',
|
|
73
73
|
tls: Object.freeze({
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
// Chromium's list, in Chromium's order, RESTRICTED to what this package can perform. It offers
|
|
75
|
+
// sixteen; the eight left out are TLS 1.2 CBC, RSA key exchange and the 1.2 ChaCha20 suites,
|
|
76
|
+
// none of which this package implements. Listing them would have been the exact dishonesty the
|
|
77
|
+
// requires-check exists to prevent: in a 1.3 handshake they are ignored, but a 1.2 server can
|
|
78
|
+
// select one and get a dead connection. 0x1303 is present because ChaCha20 is injectable and
|
|
79
|
+
// this profile requires it.
|
|
80
|
+
ciphers: Object.freeze([0x1301, 0x1302, 0x1303, 0xc02b, 0xc02f, 0xc02c, 0xc030]),
|
|
79
81
|
groups: Object.freeze([0x11ec, 0x001d, 0x0017, 0x0018]),
|
|
82
|
+
// Chrome sends real key_shares for X25519MLKEM768 and X25519 (a GREASE entry leads, added by
|
|
83
|
+
// the grease option). Both must be generated, so both are named here; the hybrid entry is
|
|
84
|
+
// stripped, and this whole profile refused, unless an ML-KEM implementation was injected.
|
|
85
|
+
offerGroups: Object.freeze([0x11ec, 0x001d]),
|
|
80
86
|
sigSchemes: Object.freeze([0x0403, 0x0804, 0x0401, 0x0503, 0x0805, 0x0501, 0x0806, 0x0601]),
|
|
81
87
|
alpn: ['h2', 'http/1.1'],
|
|
82
88
|
// Measured: two hellos, identical extension set, entirely different orders. Chromium shuffles.
|
|
83
89
|
extensionOrder: SHUFFLE_EXTENSIONS,
|
|
84
90
|
grease: true,
|
|
85
91
|
}),
|
|
92
|
+
// Captured off the wire the same way as the TLS layer: Chrome 150 driven at this package's own
|
|
93
|
+
// TLS test server with --ignore-certificate-errors, so no root CA was installed anywhere. The
|
|
94
|
+
// ClientHello precedes certificate validation and ALPN is negotiated inside the handshake, so
|
|
95
|
+
// both fingerprints are exactly what the browser normally sends.
|
|
96
|
+
http2Settings: Object.freeze([[1, 65536], [2, 0], [4, 6291456], [6, 262144]]),
|
|
97
|
+
http2ConnectionWindow: 15663105 + 65535,
|
|
98
|
+
// m,a,s,p — NOT curl's m,s,a,p. Measured, and a difference that would have been easy to miss.
|
|
99
|
+
http2PseudoHeaderOrder: Object.freeze([':method', ':authority', ':scheme', ':path']),
|
|
100
|
+
headerOrder: Object.freeze([
|
|
101
|
+
'host',
|
|
102
|
+
'sec-ch-ua', 'sec-ch-ua-mobile', 'sec-ch-ua-platform',
|
|
103
|
+
'upgrade-insecure-requests', 'user-agent', 'accept',
|
|
104
|
+
'sec-fetch-site', 'sec-fetch-mode', 'sec-fetch-user', 'sec-fetch-dest',
|
|
105
|
+
'accept-encoding', 'accept-language', 'priority',
|
|
106
|
+
'*',
|
|
107
|
+
'content-length', 'content-type',
|
|
108
|
+
]),
|
|
86
109
|
headers: Object.freeze([['Accept-Encoding', 'gzip, deflate, br, zstd']]),
|
|
87
|
-
|
|
110
|
+
// http2:captured is gone — it is captured now. What remains is what this package cannot yet
|
|
111
|
+
// PERFORM, which is a different kind of gap and the only kind that can make an offer dishonest.
|
|
88
112
|
requires: Object.freeze([
|
|
89
113
|
'cipher:chacha20',
|
|
90
114
|
'group:x25519mlkem768',
|
|
91
115
|
'decoder:br',
|
|
92
116
|
'decoder:zstd',
|
|
93
|
-
'http2:captured',
|
|
94
117
|
]),
|
|
95
118
|
});
|
|
96
119
|
|
|
@@ -116,12 +139,18 @@ export function applyProfile(options) {
|
|
|
116
139
|
);
|
|
117
140
|
}
|
|
118
141
|
|
|
142
|
+
// A profile may carry its own implementations — `tunnelfetch/profile/chrome` bundles the two
|
|
143
|
+
// WASM primitives, and importing it is the opt-in. So a requirement is satisfied by either the
|
|
144
|
+
// caller's options OR the profile itself; checking only the options made a self-sufficient
|
|
145
|
+
// profile refuse itself.
|
|
146
|
+
const supplied = (kind, what) =>
|
|
147
|
+
Boolean(options[kind]?.[what] ?? p[kind]?.[what]);
|
|
119
148
|
const missing = [];
|
|
120
149
|
for (const need of p.requires ?? []) {
|
|
121
150
|
const [kind, what] = need.split(':');
|
|
122
|
-
if (kind === 'decoder' && !
|
|
123
|
-
if (kind === 'cipher' && !
|
|
124
|
-
if (kind === 'group' && !
|
|
151
|
+
if (kind === 'decoder' && !supplied('decoders', what)) missing.push(need);
|
|
152
|
+
if (kind === 'cipher' && !supplied('ciphers', what)) missing.push(need);
|
|
153
|
+
if (kind === 'group' && !supplied('groups', what)) missing.push(need);
|
|
125
154
|
// A profile with no captured h2 layer must not be run over HTTP/2, or it presents this
|
|
126
155
|
// identity's ClientHello above a different client's preface.
|
|
127
156
|
if (kind === 'http2' && options.http2 !== false) missing.push(need);
|
|
@@ -132,14 +161,19 @@ export function applyProfile(options) {
|
|
|
132
161
|
`the "${p.name}" profile cannot be presented honestly: ${missing.join(', ')} ` +
|
|
133
162
|
`${missing.length === 1 ? 'is' : 'are'} missing. A fingerprint field this package cannot ` +
|
|
134
163
|
'perform is an offer a server may take and then find unhonoured, which fails the ' +
|
|
135
|
-
'connection rather than merely looking wrong.
|
|
136
|
-
|
|
164
|
+
'connection rather than merely looking wrong. For the Chrome identity with its two WASM ' +
|
|
165
|
+
"primitives already wired in, import { chrome } from 'tunnelfetch/profile/chrome'; " +
|
|
166
|
+
'otherwise supply the missing pieces yourself through `decoders`, `ciphers` and `groups`.',
|
|
137
167
|
{ profile: p.name, missing },
|
|
138
168
|
);
|
|
139
169
|
}
|
|
140
170
|
|
|
141
171
|
const out = { ...options };
|
|
142
172
|
if (p.tls) out.tls = { ...p.tls, ...(options.tls ?? {}) };
|
|
173
|
+
// Implementations the profile brings, with the caller's taking precedence.
|
|
174
|
+
for (const kind of ['ciphers', 'groups', 'decoders']) {
|
|
175
|
+
if (p[kind]) out[kind] = { ...p[kind], ...(options[kind] ?? {}) };
|
|
176
|
+
}
|
|
143
177
|
for (const key of ['headerOrder', 'http2Settings', 'http2PseudoHeaderOrder', 'http2HpackIndexing']) {
|
|
144
178
|
if (options[key] === undefined && p[key] != null) out[key] = p[key];
|
|
145
179
|
}
|
package/src/tls/aead.js
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import { TlsError, TlsUnsupportedError, codes, hex16 } from '../errors.js';
|
|
22
22
|
import { concat, u8, u16 } from '../util/bytes.js';
|
|
23
23
|
import {
|
|
24
|
+
CIPHER,
|
|
24
25
|
CIPHER_PARAMS, CIPHER_NAME, MAX_PLAINTEXT, LEGACY_VERSION, TLS12, TLS13,
|
|
25
26
|
} from './constants.js';
|
|
26
27
|
|
|
@@ -88,6 +89,12 @@ function seq64(seq) {
|
|
|
88
89
|
* @property {Uint8Array} key
|
|
89
90
|
* @property {Uint8Array} iv the 12-byte static IV for TLS 1.3, the 4-byte implicit salt for
|
|
90
91
|
* TLS 1.2
|
|
92
|
+
* @property {{seal: (k: Uint8Array, n: Uint8Array, p: Uint8Array, aad: Uint8Array) => Uint8Array,
|
|
93
|
+
* open: (k: Uint8Array, n: Uint8Array, c: Uint8Array, aad: Uint8Array) => Uint8Array | null}}
|
|
94
|
+
* [impl] caller-supplied AEAD, required for ChaCha20-Poly1305 and unused otherwise. This runtime
|
|
95
|
+
* has no WebCrypto ChaCha20 — its only native path is node:crypto, and taking it would cost the
|
|
96
|
+
* package its "web platform only" property — so the implementation is injected. `open` returns
|
|
97
|
+
* null when authentication fails.
|
|
91
98
|
*/
|
|
92
99
|
|
|
93
100
|
/**
|
|
@@ -97,7 +104,7 @@ function seq64(seq) {
|
|
|
97
104
|
* @param {AeadOptions} opts
|
|
98
105
|
* @returns {Promise<Aead>}
|
|
99
106
|
*/
|
|
100
|
-
export async function createAead({ version = TLS13, cipher, key, iv }) {
|
|
107
|
+
export async function createAead({ version = TLS13, cipher, key, iv, impl = null }) {
|
|
101
108
|
const params = CIPHER_PARAMS[cipher];
|
|
102
109
|
if (!params || params.hash === undefined) {
|
|
103
110
|
throw new TlsUnsupportedError(codes.TLS_CIPHER_UNSUPPORTED,
|
|
@@ -119,8 +126,43 @@ export async function createAead({ version = TLS13, cipher, key, iv }) {
|
|
|
119
126
|
`iv is ${iv.byteLength} bytes; ${CIPHER_NAME[cipher]} needs ${wantIv} for this version`,
|
|
120
127
|
{ cipher, version });
|
|
121
128
|
}
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
// ChaCha20-Poly1305 has no WebCrypto on this runtime — feature-detected on workerd, where the
|
|
130
|
+
// only native path is node:crypto and taking it would cost the package its "web platform only"
|
|
131
|
+
// property. So the implementation is INJECTED: `impl` supplies seal/open, and without one the
|
|
132
|
+
// suite is never offered, so a ChaCha20 record can only be reached by a server negotiating a
|
|
133
|
+
// suite that was not in the offer, which negotiateCipher already refuses.
|
|
134
|
+
const isChaCha = cipher === CIPHER.TLS_CHACHA20_POLY1305_SHA256;
|
|
135
|
+
if (isChaCha && (typeof impl?.seal !== 'function' || typeof impl?.open !== 'function')) {
|
|
136
|
+
throw new TlsError(
|
|
137
|
+
codes.CONFIG_INVALID,
|
|
138
|
+
'ChaCha20-Poly1305 was negotiated but no implementation was supplied; pass one as ' +
|
|
139
|
+
'`ciphers: { chacha20: impl }` with seal(key, nonce, plaintext, aad) and open(...)',
|
|
140
|
+
{ cipher },
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
const gcmKey = isChaCha
|
|
144
|
+
? null
|
|
145
|
+
: await crypto.subtle.importKey('raw', key, { name: 'AES-GCM' }, false, ['encrypt', 'decrypt']);
|
|
146
|
+
const chachaKey = isChaCha ? key.slice() : null;
|
|
147
|
+
/** One seal, whichever cipher was negotiated. Returns ciphertext||tag. */
|
|
148
|
+
const seal = async (nonce, aad, plain) =>
|
|
149
|
+
isChaCha
|
|
150
|
+
? impl.seal(chachaKey, nonce, plain, aad)
|
|
151
|
+
: new Uint8Array(
|
|
152
|
+
await crypto.subtle.encrypt(
|
|
153
|
+
{ name: 'AES-GCM', iv: nonce, additionalData: aad, tagLength: tagLen * 8 },
|
|
154
|
+
gcmKey, plain));
|
|
155
|
+
/** One open. Returns null on authentication failure, which every caller turns into tagFailure. */
|
|
156
|
+
const open = async (nonce, aad, ct) => {
|
|
157
|
+
if (isChaCha) return impl.open(chachaKey, nonce, ct, aad);
|
|
158
|
+
try {
|
|
159
|
+
return new Uint8Array(
|
|
160
|
+
await crypto.subtle.decrypt(
|
|
161
|
+
{ name: 'AES-GCM', iv: nonce, additionalData: aad, tagLength: tagLen * 8 }, gcmKey, ct));
|
|
162
|
+
} catch {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
124
166
|
const staticIv = iv.slice(); // defensive copy: the caller may zero or reuse its buffer
|
|
125
167
|
|
|
126
168
|
const tagFailure = () => new TlsError(codes.TLS_RECORD,
|
|
@@ -152,10 +194,7 @@ export async function createAead({ version = TLS13, cipher, key, iv }) {
|
|
|
152
194
|
inner[plaintext.byteLength] = type;
|
|
153
195
|
const aad = concat([u8(23), u16(LEGACY_VERSION), u16(inner.byteLength + tagLen)]);
|
|
154
196
|
const nonce = buildNonce(staticIv, seq);
|
|
155
|
-
|
|
156
|
-
{ name: 'AES-GCM', iv: nonce, additionalData: aad, tagLength: tagLen * 8 },
|
|
157
|
-
gcmKey, inner);
|
|
158
|
-
return new Uint8Array(ct);
|
|
197
|
+
return await seal(nonce, aad, inner);
|
|
159
198
|
},
|
|
160
199
|
|
|
161
200
|
/**
|
|
@@ -177,12 +216,11 @@ export async function createAead({ version = TLS13, cipher, key, iv }) {
|
|
|
177
216
|
const nonce = buildNonce(staticIv, seq);
|
|
178
217
|
let inner;
|
|
179
218
|
try {
|
|
180
|
-
inner =
|
|
181
|
-
{ name: 'AES-GCM', iv: nonce, additionalData: header, tagLength: tagLen * 8 },
|
|
182
|
-
gcmKey, body));
|
|
219
|
+
inner = await open(nonce, header, body);
|
|
183
220
|
} catch {
|
|
184
221
|
throw tagFailure();
|
|
185
222
|
}
|
|
223
|
+
if (inner == null) throw tagFailure();
|
|
186
224
|
// Strip the zero padding to expose the real content type (RFC 8446 s5.4). Scanning
|
|
187
225
|
// from the end is not constant time, but padding length is not secret from an attacker
|
|
188
226
|
// who can measure it anyway via record timing; the RFC imposes no such requirement.
|
|
@@ -222,9 +260,7 @@ export async function createAead({ version = TLS13, cipher, key, iv }) {
|
|
|
222
260
|
const explicit = seq64(seq);
|
|
223
261
|
const nonce = concat([staticIv, explicit]);
|
|
224
262
|
const aad = concat([explicit, u8(type), u16(TLS12), u16(plaintext.byteLength)]);
|
|
225
|
-
const ct =
|
|
226
|
-
{ name: 'AES-GCM', iv: nonce, additionalData: aad, tagLength: tagLen * 8 },
|
|
227
|
-
gcmKey, plaintext));
|
|
263
|
+
const ct = await seal(nonce, aad, plaintext);
|
|
228
264
|
return concat([explicit, ct]);
|
|
229
265
|
},
|
|
230
266
|
|
|
@@ -251,12 +287,11 @@ export async function createAead({ version = TLS13, cipher, key, iv }) {
|
|
|
251
287
|
const aad = concat([seq64(seq), header.subarray(0, 3), u16(ptLen)]);
|
|
252
288
|
let plaintext;
|
|
253
289
|
try {
|
|
254
|
-
plaintext =
|
|
255
|
-
{ name: 'AES-GCM', iv: nonce, additionalData: aad, tagLength: tagLen * 8 },
|
|
256
|
-
gcmKey, body.subarray(8)));
|
|
290
|
+
plaintext = await open(nonce, aad, body.subarray(8));
|
|
257
291
|
} catch {
|
|
258
292
|
throw tagFailure();
|
|
259
293
|
}
|
|
294
|
+
if (plaintext == null) throw tagFailure();
|
|
260
295
|
return { type: header[0], plaintext };
|
|
261
296
|
},
|
|
262
297
|
};
|
package/src/tls/connect.js
CHANGED
|
@@ -30,13 +30,16 @@ import { RecordLayer } from './record.js';
|
|
|
30
30
|
import { Transcript } from './transcript.js';
|
|
31
31
|
import {
|
|
32
32
|
ALPN_HTTP11,
|
|
33
|
+
CIPHER,
|
|
33
34
|
CIPHER_PARAMS,
|
|
35
|
+
GROUP,
|
|
34
36
|
HANDSHAKE_TYPE,
|
|
35
37
|
SUPPORTED_GROUPS,
|
|
36
38
|
TLS12,
|
|
37
39
|
TLS12_CIPHERS,
|
|
38
40
|
TLS13,
|
|
39
41
|
TLS13_CIPHERS,
|
|
42
|
+
TLS13_CIPHERS_WITH_CHACHA,
|
|
40
43
|
} from './constants.js';
|
|
41
44
|
import {
|
|
42
45
|
buildClientHello,
|
|
@@ -195,11 +198,19 @@ function expectServerHello(msg, offers12) {
|
|
|
195
198
|
*/
|
|
196
199
|
|
|
197
200
|
/**
|
|
198
|
-
* Injectable nondeterminism
|
|
199
|
-
*
|
|
201
|
+
* Injectable nondeterminism and crypto primitives the platform does not provide.
|
|
202
|
+
*
|
|
203
|
+
* `randomBytes` and `generateKeyPair` supply reproducibility (a recorded session replayed in an
|
|
204
|
+
* offline test). `aead` and `kem` supply capabilities this runtime lacks entirely: ChaCha20 and
|
|
205
|
+
* ML-KEM are absent from WebCrypto here, so an implementation must be injected before the suite or
|
|
206
|
+
* group they back can be offered — a ClientHello being an offer a server may take.
|
|
200
207
|
* @typedef {object} TlsDeps
|
|
201
208
|
* @property {(n: number) => Uint8Array} [randomBytes]
|
|
202
209
|
* @property {(algorithm: object, group: number) => Promise<CryptoKeyPair>} [generateKeyPair]
|
|
210
|
+
* @property {{ chacha20?: import('./aead.js').AeadOptions['impl'] }} [aead] injected AEAD
|
|
211
|
+
* implementations by name; `chacha20` gates and performs TLS_CHACHA20_POLY1305_SHA256
|
|
212
|
+
* @property {{ x25519mlkem768?: import('./hybrid.js').MlKem768 }} [kem] injected KEM
|
|
213
|
+
* implementations by name; `x25519mlkem768` gates and performs the X25519MLKEM768 hybrid group
|
|
203
214
|
*/
|
|
204
215
|
|
|
205
216
|
/**
|
|
@@ -254,6 +265,9 @@ export async function connectTls({ transport, hostname, verifyPeer, options = {}
|
|
|
254
265
|
const record = new RecordLayer(transport, {
|
|
255
266
|
maxHandshakeMessage: options.maxHandshakeMessage,
|
|
256
267
|
maxKeyUpdates: options.maxKeyUpdates,
|
|
268
|
+
// ChaCha20-Poly1305 has no WebCrypto path here; its seal/open are injected via deps.aead and
|
|
269
|
+
// threaded to every createAead. Null for the AES-GCM-only default, which needs nothing.
|
|
270
|
+
aeadImpls: deps.aead ?? null,
|
|
257
271
|
});
|
|
258
272
|
// Until the ServerHello picks, the record layer speaks the LOWEST version offered. The two
|
|
259
273
|
// semantics that differ before any ServerHello are alert tolerance and CCS handling, and the
|
|
@@ -282,15 +296,36 @@ async function drive({ record, hostname, verifyPeer, options, deps, versions })
|
|
|
282
296
|
const offers13 = versions.includes(TLS13);
|
|
283
297
|
const offers12 = versions.includes(TLS12);
|
|
284
298
|
const alpn = options.alpn ?? [ALPN_HTTP11];
|
|
285
|
-
|
|
286
|
-
|
|
299
|
+
|
|
300
|
+
// The two capability-gated primitives. A ClientHello is an offer a server may take, so neither
|
|
301
|
+
// the ChaCha20 suite nor the X25519MLKEM768 group may appear on the wire unless an implementation
|
|
302
|
+
// was injected — this runtime can perform neither on its own. Both are filtered out of ANY offer
|
|
303
|
+
// list (explicit or default) when their implementation is absent, which is what makes them
|
|
304
|
+
// impossible to advertise dishonestly.
|
|
305
|
+
const chacha = deps.aead?.chacha20;
|
|
306
|
+
const mlkem = deps.kem?.x25519mlkem768;
|
|
307
|
+
|
|
308
|
+
// supported_groups, and the groups a real key_share is sent for. With ML-KEM injected the
|
|
309
|
+
// default matches curl: X25519MLKEM768 first in both, alongside x25519. Without it, the classical
|
|
310
|
+
// default is unchanged and the hybrid group is stripped from any explicit list.
|
|
311
|
+
let groups = options.groups ?? (mlkem ? [GROUP.x25519mlkem768, ...SUPPORTED_GROUPS] : SUPPORTED_GROUPS);
|
|
312
|
+
let offerGroups =
|
|
313
|
+
options.offerGroups ?? (mlkem ? [GROUP.x25519mlkem768, SUPPORTED_GROUPS[0]] : DEFAULT_OFFER_GROUPS);
|
|
314
|
+
if (!mlkem) {
|
|
315
|
+
groups = groups.filter((g) => g !== GROUP.x25519mlkem768);
|
|
316
|
+
offerGroups = offerGroups.filter((g) => g !== GROUP.x25519mlkem768);
|
|
317
|
+
}
|
|
318
|
+
|
|
287
319
|
// Suites for every offered version, 1.3 first. negotiateCipher later re-checks the family of
|
|
288
320
|
// the server's pick against the negotiated version, so a union offer cannot be abused to run
|
|
289
|
-
// a 1.3 suite under 1.2 or the reverse.
|
|
290
|
-
|
|
291
|
-
|
|
321
|
+
// a 1.3 suite under 1.2 or the reverse. With ChaCha20 injected the DEFAULT switches to curl's
|
|
322
|
+
// captured TLS 1.3 order (AES-256-GCM, ChaCha20, AES-128-GCM); an explicit list keeps its own
|
|
323
|
+
// order and simply has 0x1303 filtered out when no implementation is present.
|
|
324
|
+
let ciphers = options.ciphers ?? [
|
|
325
|
+
...(offers13 ? (chacha ? TLS13_CIPHERS_WITH_CHACHA : TLS13_CIPHERS) : []),
|
|
292
326
|
...(offers12 ? TLS12_CIPHERS : []),
|
|
293
327
|
];
|
|
328
|
+
if (!chacha) ciphers = ciphers.filter((c) => c !== CIPHER.TLS_CHACHA20_POLY1305_SHA256);
|
|
294
329
|
|
|
295
330
|
// --- resumption offer ----------------------------------------------------------------------
|
|
296
331
|
// Everything about the offered PSK that later steps need is derived once, up front: the Early
|
package/src/tls/constants.js
CHANGED
|
@@ -81,7 +81,7 @@ export const CIPHER = {
|
|
|
81
81
|
// TLS 1.3
|
|
82
82
|
TLS_AES_128_GCM_SHA256: 0x1301,
|
|
83
83
|
TLS_AES_256_GCM_SHA384: 0x1302,
|
|
84
|
-
TLS_CHACHA20_POLY1305_SHA256: 0x1303, //
|
|
84
|
+
TLS_CHACHA20_POLY1305_SHA256: 0x1303, // offered only when an implementation is injected
|
|
85
85
|
// TLS 1.2, ECDHE + AEAD only
|
|
86
86
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: 0xc02b,
|
|
87
87
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: 0xc02f,
|
|
@@ -93,13 +93,39 @@ export const CIPHER = {
|
|
|
93
93
|
export const CIPHER_NAME = Object.fromEntries(Object.entries(CIPHER).map(([k, v]) => [v, k]));
|
|
94
94
|
|
|
95
95
|
/** Offered in ClientHello, in preference order. */
|
|
96
|
-
|
|
96
|
+
// curl's order, captured off the wire: `0x1302 0x1303 0x1301`, AES-256 before AES-128. Everything
|
|
97
|
+
// through 1.3.0 offered the reverse — the extension order and the header order were matched to curl
|
|
98
|
+
// and the CIPHER order was never checked, though JA3 hashes it just as directly.
|
|
99
|
+
//
|
|
100
|
+
// Client preference is advisory: most servers impose their own, so what this mainly changes is the
|
|
101
|
+
// fingerprint. Where a server does follow the client it now picks AES-256, which on this runtime
|
|
102
|
+
// costs a little more CPU per byte than AES-128 and is what curl asks for.
|
|
103
|
+
export const TLS13_CIPHERS = [CIPHER.TLS_AES_256_GCM_SHA384, CIPHER.TLS_AES_128_GCM_SHA256];
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* curl 8.21.0 / OpenSSL 3.6.3 offers its TLS 1.3 suites in this exact order — AES-256-GCM,
|
|
107
|
+
* ChaCha20-Poly1305, AES-128-GCM — captured off the wire 2026-08-01 (`0x1302 0x1303 0x1301`).
|
|
108
|
+
* ChaCha20 is SECOND, right after AES-256-GCM; that is "curl's position" for it.
|
|
109
|
+
*
|
|
110
|
+
* TLS13_CIPHERS above leads with AES-128, which is the order this package has always offered and
|
|
111
|
+
* which the offline test server keys its default suite selection off; reordering it would change
|
|
112
|
+
* the negotiated suite across the whole suite. So this curl-faithful order is used ONLY when a
|
|
113
|
+
* ChaCha20 implementation has been injected — i.e. when the caller has opted into being able to
|
|
114
|
+
* perform every suite curl offers — and never otherwise. See connect.js.
|
|
115
|
+
*/
|
|
116
|
+
export const TLS13_CIPHERS_WITH_CHACHA = [
|
|
117
|
+
CIPHER.TLS_AES_256_GCM_SHA384,
|
|
118
|
+
CIPHER.TLS_CHACHA20_POLY1305_SHA256,
|
|
119
|
+
CIPHER.TLS_AES_128_GCM_SHA256,
|
|
120
|
+
];
|
|
97
121
|
|
|
122
|
+
// Likewise curl's relative order among the four suites this package implements: of its full list,
|
|
123
|
+
// `0xc02c 0xc030 ... 0xc02b 0xc02f` — ECDSA before RSA within each strength, AES-256 before AES-128.
|
|
98
124
|
export const TLS12_CIPHERS = [
|
|
99
|
-
CIPHER.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
100
|
-
CIPHER.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
101
125
|
CIPHER.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
102
126
|
CIPHER.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
127
|
+
CIPHER.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
128
|
+
CIPHER.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
103
129
|
];
|
|
104
130
|
|
|
105
131
|
/**
|
|
@@ -118,6 +144,14 @@ export const TLS12_CIPHERS = [
|
|
|
118
144
|
export const CIPHER_PARAMS = {
|
|
119
145
|
[CIPHER.TLS_AES_128_GCM_SHA256]: { hash: 'SHA-256', hashLen: 32, keyLen: 16, ivLen: 12, tagLen: 16 },
|
|
120
146
|
[CIPHER.TLS_AES_256_GCM_SHA384]: { hash: 'SHA-384', hashLen: 48, keyLen: 32, ivLen: 12, tagLen: 16 },
|
|
147
|
+
// Parameters only. Deliberately NOT in TLS13_CIPHERS, so it is never offered unless a caller
|
|
148
|
+
// supplies an implementation — this runtime has no WebCrypto ChaCha20, and its only native path
|
|
149
|
+
// is node:crypto, which the package will not require. Having the parameters here lets the AEAD
|
|
150
|
+
// layer refuse with "no implementation supplied" rather than "unknown suite", which is the
|
|
151
|
+
// difference between a fixable configuration and an apparent dead end.
|
|
152
|
+
[CIPHER.TLS_CHACHA20_POLY1305_SHA256]: {
|
|
153
|
+
hash: 'SHA-256', hashLen: 32, keyLen: 32, ivLen: 12, tagLen: 16,
|
|
154
|
+
},
|
|
121
155
|
[CIPHER.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256]: {
|
|
122
156
|
hash: 'SHA-256', hashLen: 32, keyLen: 16, ivLen: 12, tagLen: 16, fixedIvLen: 4, sig: 'ecdsa',
|
|
123
157
|
},
|
|
@@ -141,6 +175,11 @@ export const GROUP = {
|
|
|
141
175
|
x25519: 0x001d,
|
|
142
176
|
x448: 0x001e,
|
|
143
177
|
ffdhe2048: 0x0100,
|
|
178
|
+
// Post-quantum hybrid (draft-kwiatkowski-tls-ecdhe-mlkem): ML-KEM-768 + X25519. Reachable only
|
|
179
|
+
// when an ML-KEM implementation is injected — its key exchange is not a WebCrypto primitive on
|
|
180
|
+
// this runtime — so like ChaCha20 it is never offered unless the capability was supplied. The
|
|
181
|
+
// combiner lives in hybrid.js; GROUP_PARAMS below records only the wire sizes, not an algorithm.
|
|
182
|
+
x25519mlkem768: 0x11ec,
|
|
144
183
|
};
|
|
145
184
|
|
|
146
185
|
export const GROUP_NAME = Object.fromEntries(Object.entries(GROUP).map(([k, v]) => [v, k]));
|
|
@@ -154,10 +193,14 @@ export const SUPPORTED_GROUPS = [GROUP.x25519, GROUP.secp256r1, GROUP.secp384r1,
|
|
|
154
193
|
|
|
155
194
|
/**
|
|
156
195
|
* WebCrypto parameters per group, discriminated on `kind` because X25519 sizes its shared
|
|
157
|
-
* secret in bytes while ECDH sizes it in bits
|
|
196
|
+
* secret in bytes while ECDH sizes it in bits, and the ML-KEM hybrid is not a WebCrypto
|
|
197
|
+
* primitive at all — it carries wire sizes only, and hybrid.js owns the crypto.
|
|
158
198
|
* @typedef {{ kind: 'x25519', algorithm: { name: string }, publicLen: number, secretLen: number }
|
|
159
199
|
* | { kind: 'ec', algorithm: { name: string, namedCurve: string }, publicLen: number,
|
|
160
|
-
* secretBits: number }
|
|
200
|
+
* secretBits: number }
|
|
201
|
+
* | { kind: 'hybrid', clientShareLen: number, serverShareLen: number, secretLen: number,
|
|
202
|
+
* mlkemPublicLen: number, mlkemSecretKeyLen: number, mlkemCiphertextLen: number,
|
|
203
|
+
* classicalPublicLen: number, classicalSecretLen: number }} GroupParams
|
|
161
204
|
*/
|
|
162
205
|
|
|
163
206
|
/**
|
|
@@ -175,6 +218,17 @@ export const GROUP_PARAMS = {
|
|
|
175
218
|
[GROUP.secp521r1]: {
|
|
176
219
|
kind: 'ec', algorithm: { name: 'ECDH', namedCurve: 'P-521' }, publicLen: 133, secretBits: 528,
|
|
177
220
|
},
|
|
221
|
+
// X25519MLKEM768 (draft-kwiatkowski-tls-ecdhe-mlkem). The wire sizes below are FIPS 203
|
|
222
|
+
// ML-KEM-768 (ek 1184, ct 1088, dk 2400) alongside X25519 (32). The client's key_share is
|
|
223
|
+
// 1184 + 32 = 1216 bytes and the server's is 1088 + 32 = 1120; the shared secret fed to the
|
|
224
|
+
// key schedule is 32 + 32 = 64. Ordering (ML-KEM before X25519, in both the shares and the
|
|
225
|
+
// secret) is spelled out and enforced in hybrid.js — it is the whole subtlety of this group.
|
|
226
|
+
[GROUP.x25519mlkem768]: {
|
|
227
|
+
kind: 'hybrid',
|
|
228
|
+
clientShareLen: 1216, serverShareLen: 1120, secretLen: 64,
|
|
229
|
+
mlkemPublicLen: 1184, mlkemSecretKeyLen: 2400, mlkemCiphertextLen: 1088,
|
|
230
|
+
classicalPublicLen: 32, classicalSecretLen: 32,
|
|
231
|
+
},
|
|
178
232
|
};
|
|
179
233
|
|
|
180
234
|
// -------------------------------------------------------------------- signature schemes
|