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.
@@ -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 fields → { $b: base64 }
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
  };