@reclaimprotocol/tls
Version:
TLS 1.2/1.3 for any JavaScript Environment
52 lines (51 loc) • 2.43 kB
JavaScript
import { crypto } from "../crypto/index.js";
import { getHash, hkdfExtractAndExpandLabel } from "../utils/decryption-utils.js";
import { SUPPORTED_CIPHER_SUITE_MAP } from "./constants.js";
import { uint8ArrayToDataView } from "./generics.js";
import { expectReadWithLength } from "./packets.js";
export function parseSessionTicket(data) {
const lifetimeS = read(4).getUint32(0);
const ticketAgeAddMs = read(4).getUint32(0);
const nonce = readWLength(1);
const ticket = readWLength(2);
const extensions = readWLength(2);
const sessionTicket = {
ticket,
lifetimeS,
ticketAgeAddMs,
nonce,
expiresAt: new Date(Date.now() + lifetimeS * 1000),
extensions
};
return sessionTicket;
function read(bytes) {
const result = data.slice(0, bytes);
data = data.slice(bytes);
return uint8ArrayToDataView(result);
}
function readWLength(bytesLength = 2) {
const content = expectReadWithLength(data, bytesLength);
data = data.slice(content.length + bytesLength);
return content;
}
}
export async function getPskFromTicket(ticket, { masterKey, hellos, cipherSuite }) {
const { hashAlgorithm, hashLength } = SUPPORTED_CIPHER_SUITE_MAP[cipherSuite];
const handshakeHash = await getHash(hellos, cipherSuite);
const resumeMasterSecret = await hkdfExtractAndExpandLabel(hashAlgorithm, masterKey, 'res master', handshakeHash, hashLength);
const psk = await hkdfExtractAndExpandLabel(hashAlgorithm, resumeMasterSecret, 'resumption', ticket.nonce, hashLength);
const emptyHash = await crypto.hash(hashAlgorithm, new Uint8Array());
const earlySecret = await crypto.extract(hashAlgorithm, hashLength, psk, '');
const binderKey = await hkdfExtractAndExpandLabel(hashAlgorithm, earlySecret, 'res binder', emptyHash, hashLength);
// const clientEarlyTrafficSecret = hkdfExtractAndExpandLabel(hashAlgorithm, earlySecret, 'c e traffic', new Uint8Array(), hashLength)
const finishKey = await hkdfExtractAndExpandLabel(hashAlgorithm, binderKey, 'finished', new Uint8Array(), hashLength);
const ticketAge = Math.floor(ticket.lifetimeS / 1000 + ticket.ticketAgeAddMs);
return {
identity: ticket.ticket,
ticketAge,
finishKey: await crypto.importKey(hashAlgorithm, finishKey),
resumeMasterSecret,
earlySecret,
cipherSuite,
};
}