lemon-tls 0.7.0 → 0.9.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 +253 -20
- package/index.d.ts +94 -6
- package/index.js +126 -0
- package/package.json +1 -1
- package/src/compat.js +316 -45
- package/src/crypto.js +19 -0
- package/src/dtls_session.js +62 -6
- package/src/dtls_socket.js +32 -0
- package/src/node_options.js +138 -0
- package/src/record.js +72 -5
- package/src/secure_context.js +49 -4
- package/src/session/cert_compression.js +157 -0
- package/src/session/ecdh.js +237 -10
- package/src/session/ech.js +715 -0
- package/src/session/hpke.js +414 -0
- package/src/session/message.js +39 -4
- package/src/session/signing.js +56 -3
- package/src/session/ticket.js +38 -25
- package/src/tls_session.js +2825 -195
- package/src/tls_socket.js +839 -148
- package/src/utils.js +68 -1
- package/src/wire.js +148 -9
package/src/session/ticket.js
CHANGED
|
@@ -122,6 +122,25 @@ function encode_client_session(state) {
|
|
|
122
122
|
* @param {Uint8Array|Buffer} blob
|
|
123
123
|
* @returns {Object|null}
|
|
124
124
|
*/
|
|
125
|
+
/**
|
|
126
|
+
* What an application may know of a client session blob ('session' event)
|
|
127
|
+
* without its secrets: { version, servername, alpn, created, expiresAt (ms),
|
|
128
|
+
* earlyData (whether its ticket allows 0-RTT) } — or null for a blob that is
|
|
129
|
+
* not one. For a cache to drop what has expired.
|
|
130
|
+
*/
|
|
131
|
+
function client_session_info(blob) {
|
|
132
|
+
let s = decode_client_session(blob);
|
|
133
|
+
if (!s) return null;
|
|
134
|
+
return {
|
|
135
|
+
version: s.v === 13 ? 'TLSv1.3' : s.v === 12 ? 'TLSv1.2' : null,
|
|
136
|
+
servername: s.sni != null ? s.sni : null,
|
|
137
|
+
alpn: s.alpn != null ? s.alpn : null,
|
|
138
|
+
created: typeof s.created === 'number' ? s.created : null,
|
|
139
|
+
expiresAt: typeof s.created === 'number' && typeof s.lifetime === 'number' ? s.created + s.lifetime * 1000 : null,
|
|
140
|
+
earlyData: !!(s.max_early_data > 0),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
125
144
|
function decode_client_session(blob) {
|
|
126
145
|
try {
|
|
127
146
|
if (!blob || blob.length === 0) return null;
|
|
@@ -138,22 +157,19 @@ function decode_client_session(blob) {
|
|
|
138
157
|
|
|
139
158
|
/**
|
|
140
159
|
* Convert state object to JSON-safe form.
|
|
141
|
-
* Uint8Array/Buffer
|
|
160
|
+
* Uint8Array/Buffer values → { $b: base64 }, inside objects and arrays alike
|
|
161
|
+
* (a client blob holds the server's certificate chain: an array of DER).
|
|
142
162
|
*/
|
|
163
|
+
function serialize_value(v) {
|
|
164
|
+
if (v == null) return null;
|
|
165
|
+
if (v instanceof Uint8Array || Buffer.isBuffer(v)) return { $b: Buffer.from(v).toString('base64') };
|
|
166
|
+
if (Array.isArray(v)) return v.map(serialize_value);
|
|
167
|
+
if (typeof v === 'object') return serialize_state(v);
|
|
168
|
+
return v;
|
|
169
|
+
}
|
|
143
170
|
function serialize_state(state) {
|
|
144
171
|
let out = {};
|
|
145
|
-
for (let k in state)
|
|
146
|
-
let v = state[k];
|
|
147
|
-
if (v == null) {
|
|
148
|
-
out[k] = null;
|
|
149
|
-
} else if (v instanceof Uint8Array || Buffer.isBuffer(v)) {
|
|
150
|
-
out[k] = { $b: Buffer.from(v).toString('base64') };
|
|
151
|
-
} else if (typeof v === 'object' && !Array.isArray(v)) {
|
|
152
|
-
out[k] = serialize_state(v);
|
|
153
|
-
} else {
|
|
154
|
-
out[k] = v;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
172
|
+
for (let k in state) out[k] = serialize_value(state[k]);
|
|
157
173
|
return out;
|
|
158
174
|
}
|
|
159
175
|
|
|
@@ -161,21 +177,17 @@ function serialize_state(state) {
|
|
|
161
177
|
* Convert JSON-decoded form back to state object.
|
|
162
178
|
* { $b: base64 } → Uint8Array
|
|
163
179
|
*/
|
|
180
|
+
function deserialize_value(v) {
|
|
181
|
+
if (v == null) return null;
|
|
182
|
+
if (Array.isArray(v)) return v.map(deserialize_value);
|
|
183
|
+
if (typeof v === 'object' && typeof v.$b === 'string' && Object.keys(v).length === 1) return new Uint8Array(Buffer.from(v.$b, 'base64'));
|
|
184
|
+
if (typeof v === 'object') return deserialize_state(v);
|
|
185
|
+
return v;
|
|
186
|
+
}
|
|
164
187
|
function deserialize_state(obj) {
|
|
165
188
|
if (obj == null) return null;
|
|
166
189
|
let out = {};
|
|
167
|
-
for (let k in obj)
|
|
168
|
-
let v = obj[k];
|
|
169
|
-
if (v == null) {
|
|
170
|
-
out[k] = null;
|
|
171
|
-
} else if (typeof v === 'object' && typeof v.$b === 'string' && Object.keys(v).length === 1) {
|
|
172
|
-
out[k] = new Uint8Array(Buffer.from(v.$b, 'base64'));
|
|
173
|
-
} else if (typeof v === 'object' && !Array.isArray(v)) {
|
|
174
|
-
out[k] = deserialize_state(v);
|
|
175
|
-
} else {
|
|
176
|
-
out[k] = v;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
190
|
+
for (let k in obj) out[k] = deserialize_value(obj[k]);
|
|
179
191
|
return out;
|
|
180
192
|
}
|
|
181
193
|
|
|
@@ -183,6 +195,7 @@ export {
|
|
|
183
195
|
encrypt_session_blob,
|
|
184
196
|
decrypt_session_blob,
|
|
185
197
|
encode_client_session,
|
|
198
|
+
client_session_info,
|
|
186
199
|
decode_client_session,
|
|
187
200
|
split_ticket_keys,
|
|
188
201
|
};
|