From 1fcc365d9e04568235e7a0dd6ff249586c6ad818 Mon Sep 17 00:00:00 2001
From: c65722 <53181351+c65722@users.noreply.github.com>
Date: Sat, 20 Jul 2019 07:58:33 -0700
Subject: [PATCH] Add Parse TLS record operation
---
src/core/config/Categories.json | 1 +
src/core/lib/Protocol.mjs | 3 +
src/core/operations/ParseTLSRecord.mjs | 884 +++++++++
tests/operations/index.mjs | 1 +
tests/operations/tests/ParseTLSRecord.mjs | 2045 +++++++++++++++++++++
5 files changed, 2934 insertions(+)
create mode 100644 src/core/operations/ParseTLSRecord.mjs
create mode 100644 tests/operations/tests/ParseTLSRecord.mjs
diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json
index bebdd6a5..bd29dcb2 100644
--- a/src/core/config/Categories.json
+++ b/src/core/config/Categories.json
@@ -235,6 +235,7 @@
"Parse IPv6 address",
"Parse IPv4 header",
"Parse TCP",
+ "Parse TLS record",
"Parse UDP",
"Parse SSH Host Key",
"Parse URI",
diff --git a/src/core/lib/Protocol.mjs b/src/core/lib/Protocol.mjs
index 57d2374a..dfb8b197 100644
--- a/src/core/lib/Protocol.mjs
+++ b/src/core/lib/Protocol.mjs
@@ -26,6 +26,9 @@ export function objToTable(obj, nested=false) {
`;
for (const key in obj) {
+ if (typeof obj[key] === "function")
+ continue;
+
html += `
${key} | `;
if (typeof obj[key] === "object")
html += `${objToTable(obj[key], true)} | `;
diff --git a/src/core/operations/ParseTLSRecord.mjs b/src/core/operations/ParseTLSRecord.mjs
new file mode 100644
index 00000000..57a339a8
--- /dev/null
+++ b/src/core/operations/ParseTLSRecord.mjs
@@ -0,0 +1,884 @@
+/**
+ * @author c65722 []
+ * @copyright Crown Copyright 2024
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation.mjs";
+import {toHexFast} from "../lib/Hex.mjs";
+import {objToTable} from "../lib/Protocol.mjs";
+import Stream from "../lib/Stream.mjs";
+
+/**
+ * Parse TLS record operation.
+ */
+class ParseTLSRecord extends Operation {
+
+ /**
+ * ParseTLSRecord constructor.
+ */
+ constructor() {
+ super();
+
+ this.name = "Parse TLS record";
+ this.module = "Default";
+ this.description = "Parses one or more TLS records";
+ this.infoURL = "https://wikipedia.org/wiki/Transport_Layer_Security";
+ this.inputType = "ArrayBuffer";
+ this.outputType = "json";
+ this.presentType = "html";
+ this.args = [];
+ this._handshakeParser = new HandshakeParser();
+ this._contentTypes = new Map();
+
+ for (const key in ContentType) {
+ this._contentTypes[ContentType[key]] = key.toString().toLocaleLowerCase();
+ }
+ }
+
+ /**
+ * @param {ArrayBuffer} input - Stream, containing one or more raw TLS Records.
+ * @param {Object[]} args
+ * @returns {Object[]} Array of Object representations of TLS Records contained within input.
+ */
+ run(input, args) {
+ const s = new Stream(new Uint8Array(input));
+
+ const output = [];
+
+ while (s.hasMore()) {
+ const record = this._readRecord(s);
+ if (record) {
+ output.push(record);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads a TLS Record from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw TLS Record.
+ * @returns {Object} Object representation of TLS Record.
+ */
+ _readRecord(input) {
+ const RECORD_HEADER_LEN = 5;
+
+ if (input.position + RECORD_HEADER_LEN > input.length) {
+ input.moveTo(input.length);
+
+ return null;
+ }
+
+ const type = input.readInt(1);
+ const typeString = this._contentTypes[type] ?? type.toString();
+ const version = "0x" + toHexFast(input.getBytes(2));
+ const length = input.readInt(2);
+ const content = input.getBytes(length);
+ const truncated = content.length < length;
+
+ const recordHeader = new RecordHeader(typeString, version, length, truncated);
+
+ if (!content.length) {
+ return {...recordHeader};
+ }
+
+ if (type === ContentType.HANDSHAKE) {
+ return this._handshakeParser.parse(new Stream(content), recordHeader);
+ }
+
+ const record = {...recordHeader};
+ record.value = "0x" + toHexFast(content);
+
+ return record;
+ }
+
+ /**
+ * Displays the parsed TLS Records in a tabular style.
+ *
+ * @param {Object[]} data - Array of Object representations of the TLS Records.
+ * @returns {html} HTML representation of TLS Records contained within data.
+ */
+ present(data) {
+ return data.map(r => objToTable(r)).join("\n\n");
+ }
+}
+
+export default ParseTLSRecord;
+
+/**
+ * Repesents the known values of type field of a TLS Record header.
+ */
+const ContentType = Object.freeze({
+ CHANGE_CIPHER_SPEC: 20,
+ ALERT: 21,
+ HANDSHAKE: 22,
+ APPLICATION_DATA: 23,
+});
+
+/**
+ * Represents a TLS Record header
+ */
+class RecordHeader {
+ /**
+ * RecordHeader cosntructor.
+ *
+ * @param {string} type - String representation of TLS Record type field.
+ * @param {string} version - Hex representation of TLS Record version field.
+ * @param {int} length - Length of TLS Record.
+ * @param {bool} truncated - Is TLS Record truncated.
+ */
+ constructor(type, version, length, truncated) {
+ this.type = type;
+ this.version = version;
+ this.length = length;
+
+ if (truncated) {
+ this.truncated = true;
+ }
+ }
+}
+
+/**
+ * Parses TLS Handshake messages.
+ */
+class HandshakeParser {
+
+ /**
+ * HandshakeParser constructor.
+ */
+ constructor() {
+ this._clientHelloParser = new ClientHelloParser();
+ this._serverHelloParser = new ServerHelloParser();
+ this._newSessionTicketParser = new NewSessionTicketParser();
+ this._certificateParser = new CertificateParser();
+ this._certificateRequestParser = new CertificateRequestParser();
+ this._certificateVerifyParser = new CertificateVerifyParser();
+ this._handshakeTypes = new Map();
+
+ for (const key in HandshakeType) {
+ this._handshakeTypes[HandshakeType[key]] = key.toString().toLowerCase();
+ }
+ }
+
+ /**
+ * Parses a single TLS handshake message.
+ *
+ * @param {Stream} input - Stream, containing a raw Handshake message.
+ * @param {RecordHeader} recordHeader - TLS Record header.
+ * @returns {Object} Object representation of Handshake.
+ */
+ parse(input, recordHeader) {
+ const output = {...recordHeader};
+
+ if (!input.hasMore()) {
+ return output;
+ }
+
+ const handshakeType = input.readInt(1);
+ output.handshakeType = this._handshakeTypes[handshakeType] ?? handshakeType.toString();
+
+ if (input.position + 3 > input.length) {
+ input.moveTo(input.length);
+
+ return output;
+ }
+
+ const handshakeLength = input.readInt(3);
+
+ if (handshakeLength + 4 !== recordHeader.length) {
+ input.moveTo(0);
+
+ output.handshakeType = this._handshakeTypes[HandshakeType.FINISHED];
+ output.handshakeValue = "0x" + toHexFast(input.bytes);
+
+ return output;
+ }
+
+ const content = input.getBytes(handshakeLength);
+ if (!content.length) {
+ return output;
+ }
+
+ switch (handshakeType) {
+ case HandshakeType.CLIENT_HELLO:
+ return {...output, ...this._clientHelloParser.parse(new Stream(content))};
+ case HandshakeType.SERVER_HELLO:
+ return {...output, ...this._serverHelloParser.parse(new Stream(content))};
+ case HandshakeType.NEW_SESSION_TICKET:
+ return {...output, ...this._newSessionTicketParser.parse(new Stream(content))};
+ case HandshakeType.CERTIFICATE:
+ return {...output, ...this._certificateParser.parse(new Stream(content))};
+ case HandshakeType.CERTIFICATE_REQUEST:
+ return {...output, ...this._certificateRequestParser.parse(new Stream(content))};
+ case HandshakeType.CERTIFICATE_VERIFY:
+ return {...output, ...this._certificateVerifyParser.parse(new Stream(content))};
+ default:
+ output.handshakeValue = "0x" + toHexFast(content);
+ }
+
+ return output;
+ }
+}
+
+/**
+ * Represents the known values of the msg_type field of a TLS Handshake message.
+ */
+const HandshakeType = Object.freeze({
+ HELLO_REQUEST: 0,
+ CLIENT_HELLO: 1,
+ SERVER_HELLO: 2,
+ NEW_SESSION_TICKET: 4,
+ CERTIFICATE: 11,
+ SERVER_KEY_EXCHANGE: 12,
+ CERTIFICATE_REQUEST: 13,
+ SERVER_HELLO_DONE: 14,
+ CERTIFICATE_VERIFY: 15,
+ CLIENT_KEY_EXCHANGE: 16,
+ FINISHED: 20,
+});
+
+/**
+ * Parses TLS Handshake ClientHello messages.
+ */
+class ClientHelloParser {
+
+ /**
+ * ClientHelloParser constructor.
+ */
+ constructor() {
+ this._extensionsParser = new ExtensionsParser();
+ }
+
+ /**
+ * Parses a single TLS Handshake ClientHello message.
+ *
+ * @param {Stream} input - Stream, containing a raw ClientHello message.
+ * @returns {Object} Object representation of ClientHello.
+ */
+ parse(input) {
+ const output = {};
+
+ output.clientVersion = this._readClientVersion(input);
+ output.random = this._readRandom(input);
+
+ const sessionID = this._readSessionID(input);
+ if (sessionID) {
+ output.sessionID = sessionID;
+ }
+
+ output.cipherSuites = this._readCipherSuites(input);
+ output.compressionMethods = this._readCompressionMethods(input);
+ output.extensions = this._readExtensions(input);
+
+ return output;
+ }
+
+ /**
+ * Reads the client_version field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ClientHello message, with position before client_version field.
+ * @returns {string} Hex representation of client_version.
+ */
+ _readClientVersion(input) {
+ return readBytesAsHex(input, 2);
+ }
+
+ /**
+ * Reads the random field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ClientHello message, with position before random field.
+ * @returns {string} Hex representation of random.
+ */
+ _readRandom(input) {
+ return readBytesAsHex(input, 32);
+ }
+
+ /**
+ * Reads the session_id field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ClientHello message, with position before session_id length field.
+ * @returns {string} Hex representation of session_id, or empty string if session_id not present.
+ */
+ _readSessionID(input) {
+ return readSizePrefixedBytesAsHex(input, 1);
+ }
+
+ /**
+ * Reads the cipher_suites field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ClientHello message, with position before cipher_suites length field.
+ * @returns {Object} Object represention of cipher_suites field.
+ */
+ _readCipherSuites(input) {
+ const output = {};
+
+ output.length = input.readInt(2);
+ if (!output.length) {
+ return {};
+ }
+
+ const cipherSuites = new Stream(input.getBytes(output.length));
+ if (cipherSuites.length < output.length) {
+ output.truncated = true;
+ }
+
+ output.values = [];
+
+ while (cipherSuites.hasMore()) {
+ const cipherSuite = readBytesAsHex(cipherSuites, 2);
+ if (cipherSuite) {
+ output.values.push(cipherSuite);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads the compression_methods field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ClientHello message, with position before compression_methods length field.
+ * @returns {Object} Object representation of compression_methods field.
+ */
+ _readCompressionMethods(input) {
+ const output = {};
+
+ output.length = input.readInt(1);
+ if (!output.length) {
+ return {};
+ }
+
+ const compressionMethods = new Stream(input.getBytes(output.length));
+ if (compressionMethods.length < output.length) {
+ output.truncated = true;
+ }
+
+ output.values = [];
+
+ while (compressionMethods.hasMore()) {
+ const compressionMethod = readBytesAsHex(compressionMethods, 1);
+ if (compressionMethod) {
+ output.values.push(compressionMethod);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads the extensions field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ClientHello message, with position before extensions length field.
+ * @returns {Object} Object representations of extensions field.
+ */
+ _readExtensions(input) {
+ const output = {};
+
+ output.length = input.readInt(2);
+ if (!output.length) {
+ return {};
+ }
+
+ const extensions = new Stream(input.getBytes(output.length));
+ if (extensions.length < output.length) {
+ output.truncated = true;
+ }
+
+ output.values = this._extensionsParser.parse(extensions);
+
+ return output;
+ }
+}
+
+/**
+ * Parses TLS Handshake ServeHello messages.
+ */
+class ServerHelloParser {
+
+ /**
+ * ServerHelloParser constructor.
+ */
+ constructor() {
+ this._extensionsParser = new ExtensionsParser();
+ }
+
+ /**
+ * Parses a single TLS Handshake ServerHello message.
+ *
+ * @param {Stream} input - Stream, containing a raw ServerHello message.
+ * @return {Object} Object representation of ServerHello.
+ */
+ parse(input) {
+ const output = {};
+
+ output.serverVersion = this._readServerVersion(input);
+ output.random = this._readRandom(input);
+
+ const sessionID = this._readSessionID(input);
+ if (sessionID) {
+ output.sessionID = sessionID;
+ }
+
+ output.cipherSuite = this._readCipherSuite(input);
+ output.compressionMethod = this._readCompressionMethod(input);
+ output.extensions = this._readExtensions(input);
+
+ return output;
+ }
+
+ /**
+ * Reads the server_version field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ServerHello message, with position before server_version field.
+ * @returns {string} Hex representation of server_version.
+ */
+ _readServerVersion(input) {
+ return readBytesAsHex(input, 2);
+ }
+
+ /**
+ * Reads the random field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ServerHello message, with position before random field.
+ * @returns {string} Hex representation of random.
+ */
+ _readRandom(input) {
+ return readBytesAsHex(input, 32);
+ }
+
+ /**
+ * Reads the session_id field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ServertHello message, with position before session_id length field.
+ * @returns {string} Hex representation of session_id, or empty string if session_id not present.
+ */
+ _readSessionID(input) {
+ return readSizePrefixedBytesAsHex(input, 1);
+ }
+
+ /**
+ * Reads the cipher_suite field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ServerHello message, with position before cipher_suite field.
+ * @returns {string} Hex represention of cipher_suite.
+ */
+ _readCipherSuite(input) {
+ return readBytesAsHex(input, 2);
+ }
+
+ /**
+ * Reads the compression_method field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ServerHello message, with position before compression_method field.
+ * @returns {string} Hex represention of compression_method.
+ */
+ _readCompressionMethod(input) {
+ return readBytesAsHex(input, 1);
+ }
+
+ /**
+ * Reads the extensions field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw ServerHello message, with position before extensions length field.
+ * @returns {Object} Object representation of extensions field.
+ */
+ _readExtensions(input) {
+ const output = {};
+
+ output.length = input.readInt(2);
+ if (!output.length) {
+ return {};
+ }
+
+ const extensions = new Stream(input.getBytes(output.length));
+ if (extensions.length < output.length) {
+ output.truncated = true;
+ }
+
+ output.values = this._extensionsParser.parse(extensions);
+
+ return output;
+ }
+}
+
+/**
+ * Parses TLS Handshake Hello Extensions.
+ */
+class ExtensionsParser {
+
+ /**
+ * Parses a stream of TLS Handshake Hello Extensions.
+ *
+ * @param {Stream} input - Stream, containing multiple raw Extensions, with position before first extension length field.
+ * @returns {Object[]} Array of Object representations of Extensions contained within input.
+ */
+ parse(input) {
+ const output = [];
+
+ while (input.hasMore()) {
+ const extension = this._readExtension(input);
+ if (extension) {
+ output.push(extension);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads a single Extension from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a list of Extensions, with position before the length field of the next Extension.
+ * @returns {Object} Object representation of Extension.
+ */
+ _readExtension(input) {
+ const output = {};
+
+ if (input.position + 4 > input.length) {
+ input.moveTo(input.length);
+ return null;
+ }
+
+ output.type = "0x" + toHexFast(input.getBytes(2));
+ output.length = input.readInt(2);
+ if (!output.length) {
+ return output;
+ }
+
+ const value = input.getBytes(output.length);
+ if (!value || value.length !== output.length) {
+ output.truncated = true;
+ }
+
+ if (value && value.length) {
+ output.value = "0x" + toHexFast(value);
+ }
+
+ return output;
+ }
+}
+
+/**
+ * Parses TLS Handshake NewSessionTicket messages.
+ */
+class NewSessionTicketParser {
+
+ /**
+ * Parses a single TLS Handshake NewSessionTicket message.
+ *
+ * @param {Stream} input - Stream, containing a raw NewSessionTicket message.
+ * @returns {Object} Object representation of NewSessionTicket.
+ */
+ parse(input) {
+ return {
+ ticketLifetimeHint: this._readTicketLifetimeHint(input),
+ ticket: this._readTicket(input),
+ };
+ }
+
+ /**
+ * Reads the ticket_lifetime_hint field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw NewSessionTicket message, with position before ticket_lifetime_hint field.
+ * @returns {string} Lifetime hint, in seconds.
+ */
+ _readTicketLifetimeHint(input) {
+ if (input.position + 4 > input.length) {
+ input.moveTo(input.length);
+ return "";
+ }
+
+ return input.readInt(4) + "s";
+ }
+
+ /**
+ * Reads the ticket field fromt the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw NewSessionTicket message, with position before ticket length field.
+ * @returns {string} Hex representation of ticket.
+ */
+ _readTicket(input) {
+ return readSizePrefixedBytesAsHex(input, 2);
+ }
+}
+
+/**
+ * Parses TLS Handshake Certificate messages.
+ */
+class CertificateParser {
+
+ /**
+ * Parses a single TLS Handshake Certificate message.
+ *
+ * @param {Stream} input - Stream, containing a raw Certificate message.
+ * @returns {Object} Object representation of Certificate.
+ */
+ parse(input) {
+ const output = {};
+
+ output.certificateList = this._readCertificateList(input);
+
+ return output;
+ }
+
+ /**
+ * Reads the certificate_list field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw Certificate message, with position before certificate_list length field.
+ * @returns {string[]} Array of strings, each containing a hex representation of a value within the certificate_list field.
+ */
+ _readCertificateList(input) {
+ const output = {};
+
+ if (input.position + 3 > input.length) {
+ input.moveTo(input.length);
+ return output;
+ }
+
+ output.length = input.readInt(3);
+ if (!output.length) {
+ return output;
+ }
+
+ const certificates = new Stream(input.getBytes(output.length));
+ if (certificates.length < output.length) {
+ output.truncated = true;
+ }
+
+ output.values = [];
+
+ while (certificates.hasMore()) {
+ const certificate = this._readCertificate(certificates);
+ if (certificate) {
+ output.values.push(certificate);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads a single certificate from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a list of certificicates, with position before the length field of the next certificate.
+ * @returns {string} Hex representation of certificate.
+ */
+ _readCertificate(input) {
+ return readSizePrefixedBytesAsHex(input, 3);
+ }
+}
+
+/**
+ * Parses TLS Handshake CertificateRequest messages.
+ */
+class CertificateRequestParser {
+
+ /**
+ * Parses a single TLS Handshake CertificateRequest message.
+ *
+ * @param {Stream} input - Stream, containing a raw CertificateRequest message.
+ * @return {Object} Object representation of CertificateRequest.
+ */
+ parse(input) {
+ const output = {};
+
+ output.certificateTypes = this._readCertificateTypes(input);
+ output.supportedSignatureAlgorithms = this._readSupportedSignatureAlgorithms(input);
+
+ const certificateAuthorities = this._readCertificateAuthorities(input);
+ if (certificateAuthorities.length) {
+ output.certificateAuthorities = certificateAuthorities;
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads the certificate_types field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw CertificateRequest message, with position before certificate_types length field.
+ * @return {string[]} Array of strings, each containing a hex representation of a value within the certificate_types field.
+ */
+ _readCertificateTypes(input) {
+ const output = {};
+
+ output.length = input.readInt(1);
+ if (!output.length) {
+ return {};
+ }
+
+ const certificateTypes = new Stream(input.getBytes(output.length));
+ if (certificateTypes.length < output.length) {
+ output.truncated = true;
+ }
+
+ output.values = [];
+
+ while (certificateTypes.hasMore()) {
+ const certificateType = readBytesAsHex(certificateTypes, 1);
+ if (certificateType) {
+ output.values.push(certificateType);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads the supported_signature_algorithms field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw CertificateRequest message, with position before supported_signature_algorithms length field.
+ * @returns {string[]} Array of strings, each containing a hex representation of a value within the supported_signature_algorithms field.
+ */
+ _readSupportedSignatureAlgorithms(input) {
+ const output = {};
+
+ output.length = input.readInt(2);
+ if (!output.length) {
+ return {};
+ }
+
+ const signatureAlgorithms = new Stream(input.getBytes(output.length));
+ if (signatureAlgorithms.length < output.length) {
+ output.truncated = true;
+ }
+
+ output.values = [];
+
+ while (signatureAlgorithms.hasMore()) {
+ const signatureAlgorithm = readBytesAsHex(signatureAlgorithms, 2);
+ if (signatureAlgorithm) {
+ output.values.push(signatureAlgorithm);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads the certificate_authorities field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw CertificateRequest message, with position before certificate_authorities length field.
+ * @returns {string[]} Array of strings, each containing a hex representation of a value within the certificate_authorities field.
+ */
+ _readCertificateAuthorities(input) {
+ const output = {};
+
+ output.length = input.readInt(2);
+ if (!output.length) {
+ return {};
+ }
+
+ const certificateAuthorities = new Stream(input.getBytes(output.length));
+ if (certificateAuthorities.length < output.length) {
+ output.truncated = true;
+ }
+
+ output.values = [];
+
+ while (certificateAuthorities.hasMore()) {
+ const certificateAuthority = this._readCertificateAuthority(certificateAuthorities);
+ if (certificateAuthority) {
+ output.values.push(certificateAuthority);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Reads a single certificate authority from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a list of raw certificate authorities, with position before the length field of the next certificate authority.
+ * @returns {string} Hex representation of certificate authority.
+ */
+ _readCertificateAuthority(input) {
+ return readSizePrefixedBytesAsHex(input, 2);
+ }
+}
+
+/**
+ * Parses TLS Handshake CertificateVerify messages.
+ */
+class CertificateVerifyParser {
+
+ /**
+ * Parses a single CertificateVerify Message.
+ *
+ * @param {Stream} input - Stream, containing a raw CertificateVerify message.
+ * @returns {Object} Object representation of CertificateVerify.
+ */
+ parse(input) {
+ return {
+ algorithmHash: this._readAlgorithmHash(input),
+ algorithmSignature: this._readAlgorithmSignature(input),
+ signature: this._readSignature(input),
+ };
+ }
+
+ /**
+ * Reads the algorithm.hash field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw CertificateVerify message, with position before algorithm.hash field.
+ * @return {string} Hex representation of hash algorithm.
+ */
+ _readAlgorithmHash(input) {
+ return readBytesAsHex(input, 1);
+ }
+
+ /**
+ * Reads the algorithm.signature field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw CertificateVerify message, with position before algorithm.signature field.
+ * @return {string} Hex representation of signature algorithm.
+ */
+ _readAlgorithmSignature(input) {
+ return readBytesAsHex(input, 1);
+ }
+
+ /**
+ * Reads the signature field from the following bytes in the provided Stream.
+ *
+ * @param {Stream} input - Stream, containing a raw CertificateVerify message, with position before signature field.
+ * @return {string} Hex representation of signature.
+ */
+ _readSignature(input) {
+ return readSizePrefixedBytesAsHex(input, 2);
+ }
+}
+
+/**
+ * Read the following size prefixed bytes from the provided Stream, and reuturn as a hex string.
+ *
+ * @param {Stream} input - Stream to read from.
+ * @param {int} sizePrefixLength - Length of the size prefix field.
+ * @returns {string} Hex representation of bytes read from Stream, empty string is returned if
+ * field cannot be read in full.
+ */
+function readSizePrefixedBytesAsHex(input, sizePrefixLength) {
+ const length = input.readInt(sizePrefixLength);
+ if (!length) {
+ return "";
+ }
+
+ return readBytesAsHex(input, length);
+}
+
+/**
+ * Read n bytes from the provided Stream, and return as a hex string.
+ *
+ * @param {Stream} input - Stream to read from.
+ * @param {int} n - Number of bytes to read.
+ * @returns {string} Hex representation of bytes read from Stream, or empty string if field cannot
+ * be read in full.
+ */
+function readBytesAsHex(input, n) {
+ const bytes = input.getBytes(n);
+ if (!bytes || bytes.length !== n) {
+ return "";
+ }
+
+ return "0x" + toHexFast(bytes);
+}
diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs
index 40ce7a2e..40b510a0 100644
--- a/tests/operations/index.mjs
+++ b/tests/operations/index.mjs
@@ -115,6 +115,7 @@ import "./tests/ParseObjectIDTimestamp.mjs";
import "./tests/ParseQRCode.mjs";
import "./tests/ParseSSHHostKey.mjs";
import "./tests/ParseTCP.mjs";
+import "./tests/ParseTLSRecord.mjs";
import "./tests/ParseTLV.mjs";
import "./tests/ParseUDP.mjs";
import "./tests/PEMtoHex.mjs";
diff --git a/tests/operations/tests/ParseTLSRecord.mjs b/tests/operations/tests/ParseTLSRecord.mjs
new file mode 100644
index 00000000..86db2f2c
--- /dev/null
+++ b/tests/operations/tests/ParseTLSRecord.mjs
@@ -0,0 +1,2045 @@
+/**
+ * Parse TLS record tests.
+ *
+ * @auther c65722
+ * @copyright Crown Copyright 2024
+ * @license Apache-2.0
+ */
+
+import TestRegister from "../../lib/TestRegister.mjs";
+
+TestRegister.addTests([
+ {
+ name: "Parse TLS record: Truncated header",
+ input: "16030300",
+ expectedOutput: "[]",
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Change Cipher Spec",
+ input: "140303000101",
+ expectedOutput: '[{"type":"change_cipher_spec","version":"0x0303","length":1,"value":"0x01"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Change Cipher Spec - Truncated before content",
+ input: "1403030001",
+ expectedOutput: '[{"type":"change_cipher_spec","version":"0x0303","length":1,"truncated":true}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Alert",
+ input: "150303001411770b5b5d11078535823266ec79671ed402bced",
+ expectedOutput: '[{"type":"alert","version":"0x0303","length":20,"value":"0x11770b5b5d11078535823266ec79671ed402bced"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Alert - Truncated within content",
+ input: "150303001411770b5b5d1107853582",
+ expectedOutput: '[{"type":"alert","version":"0x0303","length":20,"truncated":true,"value":"0x11770b5b5d1107853582"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Alert - Truncated before content",
+ input: "1503030014",
+ expectedOutput: '[{"type":"alert","version":"0x0303","length":20,"truncated":true}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Truncated within length",
+ input: "1603030032010000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Truncated before length",
+ input: "160303003201",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Truncated before msg type",
+ input: "1603030032",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Hello Request",
+ input: "160303000400000000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":4,"handshakeType":"hello_request"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076000004123443210200010000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated before extensions length",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107600000412344321020001",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated within compression methods",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076000004123443210200",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"truncated":true,"values":["0x00"]},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated before compression methods",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd0510760000041234432102",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"truncated":true,"values":[]},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated before compression methods length",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107600000412344321",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated within cipher suite value",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076000004123443",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{"length":4,"truncated":true,"values":["0x1234"]},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated within cipher suites",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd0510760000041234",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{"length":4,"truncated":true,"values":["0x1234"]},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated before cipher suites",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076000004",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{"length":4,"truncated":true,"values":[]},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated before cipher suites length",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd0510760000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated before session id length",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107600",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated within random",
+ input: "16030300320100002e030345cd3a31beaebd2934dd4ec2a151d7a0",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"","cipherSuites":{},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated before random",
+ input: "16030300320100002e0303",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"","cipherSuites":{},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated within client version",
+ input: "16030300320100002e03",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello","clientVersion":"","random":"","cipherSuites":{},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, No session ID, No extensions - Truncated before client version",
+ input: "16030300320100002e",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":50,"truncated":true,"handshakeType":"client_hello"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, No extensions",
+ input: "16030300520100004e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae0004123443210200010000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":82,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","sessionID":"0xdc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, No extensions - Truncated within session id",
+ input: "16030300520100004e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":82,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, No extensions - Truncated before session id",
+ input: "16030300520100004e030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":82,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","cipherSuites":{},"compressionMethods":{},"extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, Extensions",
+ input: "160303006f0100006b030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae000412344321020001001d00000010000e00000b6578616d706c652e636f6d00170000ff01000100",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":111,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","sessionID":"0xdc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{"length":29,"values":[{"type":"0x0000","length":16,"value":"0x000e00000b6578616d706c652e636f6d"},{"type":"0x0017","length":0},{"type":"0xff01","length":1,"value":"0x00"}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, Extensions - Truncated within extension value",
+ input: "160303006f0100006b030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae000412344321020001001d00000010000e00000b657861",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":111,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","sessionID":"0xdc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{"length":29,"truncated":true,"values":[{"type":"0x0000","length":16,"truncated":true,"value":"0x000e00000b657861"}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, Extensions - Truncated before extension value",
+ input: "160303006f0100006b030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae000412344321020001001d00000010",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":111,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","sessionID":"0xdc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{"length":29,"truncated":true,"values":[{"type":"0x0000","length":16,"truncated":true}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, Extensions - Truncated within extension length",
+ input: "160303006f0100006b030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae000412344321020001001d000000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":111,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","sessionID":"0xdc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{"length":29,"truncated":true,"values":[]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, Extensions - Truncated before extension length",
+ input: "160303006f0100006b030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae000412344321020001001d0000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":111,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","sessionID":"0xdc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{"length":29,"truncated":true,"values":[]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, Extensions - Truncated within extension type",
+ input: "160303006f0100006b030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae000412344321020001001d00",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":111,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","sessionID":"0xdc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{"length":29,"truncated":true,"values":[]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Hello, Session ID, Extensions - Truncated before extension type",
+ input: "160303006f0100006b030345cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd05107620dc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae000412344321020001001d",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":111,"truncated":true,"handshakeType":"client_hello","clientVersion":"0x0303","random":"0x45cd3a31beaebd2934dd4ec2a151d7a054eab8bc0e4e5b9d4b9abdaacd051076","sessionID":"0xdc78c85fdcee405ebb7963543771005a3d1b7dbf88fb9f8df12e4f7ea525e1ae","cipherSuites":{"length":4,"values":["0x1234","0x4321"]},"compressionMethods":{"length":2,"values":["0x00","0x01"]},"extensions":{"length":29,"truncated":true,"values":[]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions",
+ input: "160303002c02000028030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132004321010000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated before extensions length",
+ input: "160303002c02000028030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113200432101",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated before compression method",
+ input: "160303002c02000028030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132004321",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","cipherSuite":"0x4321","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated within cipher suite",
+ input: "160303002c02000028030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b011320043",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","cipherSuite":"","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated before cipher suite",
+ input: "160303002c02000028030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113200",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","cipherSuite":"","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated before session id length",
+ input: "160303002c02000028030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","cipherSuite":"","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated within random",
+ input: "160303002c02000028030309684ab9c0f6e739e308cd42a18a73d9a",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"","cipherSuite":"","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated before random",
+ input: "160303002c0200002803030",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"","cipherSuite":"","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated within server version",
+ input: "160303002c0200002803",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello","serverVersion":"","random":"","cipherSuite":"","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, No session ID, No extensions - Truncated before server version",
+ input: "160303002c02000028",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":44,"truncated":true,"handshakeType":"server_hello"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, No extension",
+ input: "160303004c02000048030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220a4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b95984321010000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":76,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","sessionID":"0xa4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, No extension - Truncated within session id",
+ input: "160303004c02000048030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220a4fe3d1e9a7dc5ce3d9341b4d48a2df7",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":76,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","cipherSuite":"","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, No extension - Truncated before session id",
+ input: "160303004c02000048030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":76,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","cipherSuite":"","compressionMethod":"","extensions":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, Extensions",
+ input: "160303005902000055030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220a4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598432101000d00000000ff0100010000170000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":89,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","sessionID":"0xa4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{"length":13,"values":[{"type":"0x0000","length":0},{"type":"0xff01","length":1,"value":"0x00"},{"type":"0x0017","length":0}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, Extensions - Truncated before extension value",
+ input: "160303005902000055030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220a4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598432101000d00000000ff010001",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":89,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","sessionID":"0xa4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{"length":13,"truncated":true,"values":[{"type":"0x0000","length":0},{"type":"0xff01","length":1,"truncated":true}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, Extensions - Truncated within extension length",
+ input: "160303005902000055030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220a4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598432101000d00000000ff0100",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":89,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","sessionID":"0xa4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{"length":13,"truncated":true,"values":[{"type":"0x0000","length":0}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, Extensions - Truncated before extension length",
+ input: "160303005902000055030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220a4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598432101000d00000000ff01",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":89,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","sessionID":"0xa4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{"length":13,"truncated":true,"values":[{"type":"0x0000","length":0}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, Extensions - Truncated within extension type",
+ input: "160303005902000055030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220a4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598432101000d00000000ff",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":89,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","sessionID":"0xa4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{"length":13,"truncated":true,"values":[{"type":"0x0000","length":0}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello, Session ID, Extensions - Truncated before extension type",
+ input: "160303005902000055030309684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b0113220a4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598432101000d00000000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":89,"truncated":true,"handshakeType":"server_hello","serverVersion":"0x0303","random":"0x09684ab9c0f6e739e308cd42a18a73d9adc579378aa6b4228df7ecc422b01132","sessionID":"0xa4fe3d1e9a7dc5ce3d9341b4d48a2df755a0fd83876d0330018306707c9b9598","cipherSuite":"0x4321","compressionMethod":"0x01","extensions":{"length":13,"truncated":true,"values":[{"type":"0x0000","length":0}]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - New Session Ticket",
+ input: "16030300ca040000c60000070800c0626f6889ce97edae08b0870505f9251e1d0713438ed014ac8f5e6969cf9e500aaba6080dfed5474ec85ff48d882d526cdae7f21d51b4beeb0be83fb822f18d22d2086b7519b29114364af034ac9a6915562ba686b81917bcb89fc4a750284470e7d67d8d33647e245e5e789f547d6a1be91ef0985bbfcf3b88760586b8f02570e0b7e8547fdad75530bc0261756ec994dfc725c8551c762f26e105e62290cd43773ea9e8a42ac8ac21467053240a29ef93c2e34c2f13ce8ff494d8c64f727248",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":202,"handshakeType":"new_session_ticket","ticketLifetimeHint":"1800s","ticket":"0x626f6889ce97edae08b0870505f9251e1d0713438ed014ac8f5e6969cf9e500aaba6080dfed5474ec85ff48d882d526cdae7f21d51b4beeb0be83fb822f18d22d2086b7519b29114364af034ac9a6915562ba686b81917bcb89fc4a750284470e7d67d8d33647e245e5e789f547d6a1be91ef0985bbfcf3b88760586b8f02570e0b7e8547fdad75530bc0261756ec994dfc725c8551c762f26e105e62290cd43773ea9e8a42ac8ac21467053240a29ef93c2e34c2f13ce8ff494d8c64f727248"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - New Session Ticket - Truncated within ticket",
+ input: "16030300ca040000c60000070800c0626f6889ce97edae08b0870505f9251e1d0713438ed014ac8f5e6969cf9e500aaba6080dfed5474ec85ff48d882d526cdae7f21d51b4beeb0be83fb822f18d22d2086b7519b29114364af034ac9a6915562ba686b81917bcb89fc4a750284470",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":202,"truncated":true,"handshakeType":"new_session_ticket","ticketLifetimeHint":"1800s","ticket":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - New Session Ticket - Truncated before ticket",
+ input: "16030300ca040000c60000070800c0",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":202,"truncated":true,"handshakeType":"new_session_ticket","ticketLifetimeHint":"1800s","ticket":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - New Session Ticket - Truncated within ticket length",
+ input: "16030300ca040000c60000070800",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":202,"truncated":true,"handshakeType":"new_session_ticket","ticketLifetimeHint":"1800s","ticket":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - New Session Ticket - Truncated before ticket length",
+ input: "16030300ca040000c600000708",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":202,"truncated":true,"handshakeType":"new_session_ticket","ticketLifetimeHint":"1800s","ticket":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - New Session Ticket - Truncated within ticket lifetime hint",
+ input: "16030300ca040000c6000007",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":202,"truncated":true,"handshakeType":"new_session_ticket","ticketLifetimeHint":"","ticket":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - New Session Ticket - Truncated before ticket lifetime hint",
+ input: "16030300ca040000c6",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":202,"truncated":true,"handshakeType":"new_session_ticket"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate",
+ input: "1603030acf0b000acb000ac80002923082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf00029430820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d000599308205953082037da00302010202141521d02e945395325d99051e616ad01c97627ee2300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65332e636f6d3020170d3234303932323130303232325a180f32313234303832393130303232325a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65332e636f6d30820222300d06092a864886f70d01010105000382020f003082020a0282020100bd7c65b5c2c7027e4eb77722f84d7dc9b45f9fae45c59dd0035340b3d8fec5ea644ac4563c4260b2c078880bf81ffec0e4cd9193b708ded6431c0e7d9e8f45d595712b733262f8f62f1b4c3ae69f1f39bc68a39b1b5699adddfd7c51b83f59479fe5ffe0faef6376b1c5cea434aa9db85e792f989b5977c6fda87f7c00f79e67e417d826c1ab1fa304163414fc6321790f07cffede43170718536e5fe3128f6d101de82a7b1de37f89e61d822f09eef7304213d41998a49e5ab6b1a7eb1ab4ece21f005061828567047aaf640cff2f87c85eefc2d3a91ebf48aaa893e59451acbea894975df2587b203302fb39755f2e21e012d1fc89df86ec53723df497318d8b44eee9334a2699ad403a7df6719747bc37429d3c47ada354308380b09bb6d76e21dc1735a1479470c94c0282bbbdf5e2e6af60cf1f2e9b8dad20e45307729813eaaf584b31984e036d5452dfae47a4b8640bdf4c02ecf4ce4240d64d2ab895cbf512558712533cd3fc6838bfd24a2a588b9f1b1848bb0d6b1cd77345add6e9dc547a7b95b027bb18e96f30c4f9cd780c96984472b70ea39a7acdff9c649ac4a59e12a5a72d436036b31fa130f6a72c717b3df403113ee3b3d1605f76e57e96b83e501ed5fe9200e2ea9aefa797fa0c8b6c5d8f12e4bea7359be03d3ca35d3e22e20639fc7e03c990a494402268a08fb1589dc086995b0ba3c9ffe255b6b7cf0203010001a3533051301d0603551d0e041604143e8bac5b946c2eff6a8cb337081fa4fe6ce07312301f0603551d230418301680143e8bac5b946c2eff6a8cb337081fa4fe6ce07312300f0603551d130101ff040530030101ff300d06092a864886f70d01010b0500038202010081ad7acd39e5cc60682c962d367a84d32191e5b465ed531f617daf5fd33394a3ac9a42116d34211708ada0d9bd2cbf1d4a4175d67c87116c7495ed372c585ae6bdfe0bc713aa1afd0cc3f025c322dc45be0c3be982918dea938deaaa9e5bfd1fccb3eb8a111aec0498f64bdb16f6cb07bcecd85f6b9e445cf596d85596b4f0d7147d73cbc26000d374085e9c69f56262827fa3d5a037cf1d2cfe0f0eca779b101da08a8d732ecf584a193d93449697ee24ed6f41f9735ea3a3f206f8e6b5bf0b0ff3488a31d0feaccd701a144d35c265dc32d2e650f855debbfa5bd2d9dc2d80a1b8f81013f8049bd7be83a3ec5ae554c19fd4241a6686d4094ff073022d1f16afa5a0297e54a9b56fd469b44c6904d2b542f83ff0cf6af3b649f408f72f7cb49be5583ec4b1d912a677ae1fd81779506af9b688d8b753fdb0451925752fba8efcdaedf935f2a264caa1f4fe746ac6c339cca647b25f0bd2139205e67b6e90987da8b993b85037931443a6652426ab779db090cf08b28fed862a0ccdde1568bd930bf2d39ab7b850f97925e9bda13a6ee5166e48959711065c054bdf5ff04e4b8d5120caabca40c7707da3bb10f2ae7a00a6e56b012a6c00daaec5ddf0b63f61622aeeb81a71a5aa17508e5471e777bed8d09023c24280495adc38ffc3615dd20b139d32d7cc30b0690ab7f3e47a0131fa3d81929e64c6b9c6b363da410f6e5e",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":2767,"handshakeType":"certificate","certificateList":{"length":2760,"values":["0x3082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf","0x30820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d","0x308205953082037da00302010202141521d02e945395325d99051e616ad01c97627ee2300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65332e636f6d3020170d3234303932323130303232325a180f32313234303832393130303232325a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65332e636f6d30820222300d06092a864886f70d01010105000382020f003082020a0282020100bd7c65b5c2c7027e4eb77722f84d7dc9b45f9fae45c59dd0035340b3d8fec5ea644ac4563c4260b2c078880bf81ffec0e4cd9193b708ded6431c0e7d9e8f45d595712b733262f8f62f1b4c3ae69f1f39bc68a39b1b5699adddfd7c51b83f59479fe5ffe0faef6376b1c5cea434aa9db85e792f989b5977c6fda87f7c00f79e67e417d826c1ab1fa304163414fc6321790f07cffede43170718536e5fe3128f6d101de82a7b1de37f89e61d822f09eef7304213d41998a49e5ab6b1a7eb1ab4ece21f005061828567047aaf640cff2f87c85eefc2d3a91ebf48aaa893e59451acbea894975df2587b203302fb39755f2e21e012d1fc89df86ec53723df497318d8b44eee9334a2699ad403a7df6719747bc37429d3c47ada354308380b09bb6d76e21dc1735a1479470c94c0282bbbdf5e2e6af60cf1f2e9b8dad20e45307729813eaaf584b31984e036d5452dfae47a4b8640bdf4c02ecf4ce4240d64d2ab895cbf512558712533cd3fc6838bfd24a2a588b9f1b1848bb0d6b1cd77345add6e9dc547a7b95b027bb18e96f30c4f9cd780c96984472b70ea39a7acdff9c649ac4a59e12a5a72d436036b31fa130f6a72c717b3df403113ee3b3d1605f76e57e96b83e501ed5fe9200e2ea9aefa797fa0c8b6c5d8f12e4bea7359be03d3ca35d3e22e20639fc7e03c990a494402268a08fb1589dc086995b0ba3c9ffe255b6b7cf0203010001a3533051301d0603551d0e041604143e8bac5b946c2eff6a8cb337081fa4fe6ce07312301f0603551d230418301680143e8bac5b946c2eff6a8cb337081fa4fe6ce07312300f0603551d130101ff040530030101ff300d06092a864886f70d01010b0500038202010081ad7acd39e5cc60682c962d367a84d32191e5b465ed531f617daf5fd33394a3ac9a42116d34211708ada0d9bd2cbf1d4a4175d67c87116c7495ed372c585ae6bdfe0bc713aa1afd0cc3f025c322dc45be0c3be982918dea938deaaa9e5bfd1fccb3eb8a111aec0498f64bdb16f6cb07bcecd85f6b9e445cf596d85596b4f0d7147d73cbc26000d374085e9c69f56262827fa3d5a037cf1d2cfe0f0eca779b101da08a8d732ecf584a193d93449697ee24ed6f41f9735ea3a3f206f8e6b5bf0b0ff3488a31d0feaccd701a144d35c265dc32d2e650f855debbfa5bd2d9dc2d80a1b8f81013f8049bd7be83a3ec5ae554c19fd4241a6686d4094ff073022d1f16afa5a0297e54a9b56fd469b44c6904d2b542f83ff0cf6af3b649f408f72f7cb49be5583ec4b1d912a677ae1fd81779506af9b688d8b753fdb0451925752fba8efcdaedf935f2a264caa1f4fe746ac6c339cca647b25f0bd2139205e67b6e90987da8b993b85037931443a6652426ab779db090cf08b28fed862a0ccdde1568bd930bf2d39ab7b850f97925e9bda13a6ee5166e48959711065c054bdf5ff04e4b8d5120caabca40c7707da3bb10f2ae7a00a6e56b012a6c00daaec5ddf0b63f61622aeeb81a71a5aa17508e5471e777bed8d09023c24280495adc38ffc3615dd20b139d32d7cc30b0690ab7f3e47a0131fa3d81929e64c6b9c6b363da410f6e5e"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate - Truncated within certificate",
+ input: "1603030acf0b000acb000ac80002923082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf00029430820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d0005990x308205953082037da00302010202141521d02e945395325d99051e616ad01c97627ee2300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65332e636f6d3020170d3234303932323130303232325a180f32313234303832393130303232325a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65332e636f6d30820222300d06092a864886f70d01010105000382020f003082020a0282020100bd7c65b5c2c7027e4eb77722f84d7dc9b45f9fae45c59dd0035340b3d8fec5ea644ac4563c4260b2c078880bf81ffec0e4cd9193b708ded6431c0e7d9e8f45d595712b733262f8f62f1b4c3ae69f1f39bc68a39b1b5699adddfd7c51b83f59479fe5ffe0faef6376b1c5cea434aa9db85e792f989b5977c6fda87f7c00f79e67e417d826c1ab1fa304163414fc6321790f07cffede43170718536e5fe3128f6d101de82a7b1de37f89e61d822f09eef7304213d41998a49e5ab6b1a7eb1ab4ece21f005061828567047aaf640cff2f87c85eefc2d3a91ebf48aaa893e59451acbea894975df2587b203302fb39755f2e21e012d1fc89df86ec53723df497318d8b44eee9334a2699ad403a7df6719747bc37429d3c47ada354308380b09bb6d76e21dc1735a1479470c94c0282bbbdf5e2e6af60cf1f2e9b8dad20e45307729813eaaf584b31984e036d5452dfae47a4b8640bdf4c02ecf4ce4240d64d2ab895cbf512558712533cd3fc6838bfd24a2a588b9f1b1848bb0d6b1cd77345add6e9dc547a7b95b027bb18e96f30c4f9cd780c96984472b70ea39a7acdff9c649ac4a5",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":2767,"truncated":true,"handshakeType":"certificate","certificateList":{"length":2760,"truncated":true,"values":["0x3082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf","0x30820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate - Truncated before certificate",
+ input: "1603030acf0b000acb000ac80002923082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf00029430820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d000599",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":2767,"truncated":true,"handshakeType":"certificate","certificateList":{"length":2760,"truncated":true,"values":["0x3082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf","0x30820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate - Truncated within certificate length",
+ input: "1603030acf0b000acb000ac80002923082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf00029430820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d0005",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":2767,"truncated":true,"handshakeType":"certificate","certificateList":{"length":2760,"truncated":true,"values":["0x3082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf","0x30820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate - Truncated before certificate length",
+ input: "1603030acf0b000acb000ac80002923082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf00029430820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":2767,"truncated":true,"handshakeType":"certificate","certificateList":{"length":2760,"truncated":true,"values":["0x3082028e308201f7a003020102021468f6f88ecf1bf3d14e7503ef2e1b789cb77b86c3300d06092a864886f70d01010b05003058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d3020170d3234303932323039353335385a180f32313234303832393039353335385a3058310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643114301206035504030c0b6578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100c3df3e5745f05b3aa220ce4108838107653c3ae9584ace27d7088506ebdc3531afbe6265719278682eaa4fec7ae1f319395d356be79477bc62edbe7207d96f5717e9bd9083fdcc797c1b8e38bcf9fd08df6f101bc2a06101ddce6be2f5a0de80ebc8fdce2538867c1d6a84acef26b2068c5d27771abcee071bcf378899cb32730203010001a3533051301d0603551d0e041604144c9b134c1575c51ae9d03c4020da7541278ad928301f0603551d230418301680144c9b134c1575c51ae9d03c4020da7541278ad928300f0603551d130101ff040530030101ff300d06092a864886f70d01010b05000381810012a06cced33d721b1d7912ff0b190b74524ddfdeca103aba0f168f4f15f57212ba7d66328e48b021f32cfec84f65d79821bc1fe9f472f60c094e537160708a48a0898dbf613cece86892cf48fcd598757aa4379e18673626be2f048e35f585086ea7a3766ce50a14ca6f691b369c965e062f40619cde6262ed8019b522e76eaf","0x30820290308201f9a00302010202142a3329f5e2e92940318cecd036ff135525b1d491300d06092a864886f70d01010b05003059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d3020170d3234303932323039353531375a180f32313234303832393039353531375a3059310b30090603550406130258583115301306035504070c0c44656661756c742043697479311c301a060355040a0c1344656661756c7420436f6d70616e79204c74643115301306035504030c0c6578616d706c65322e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100b27c861d957c49111b4f37f65bc142da564429c74a925e3de6d9add55ccfccf1316a5002b3ed2d35ec9822499e7256f9caaa2191010df354185c63a32c8d080ba49510953d7ec2210685030564be69a9f2262a9da22f3623b2a9b032f3a82b1c31ce11336c288fc3d5f63565aacc8c0f85ebaad6af2cd3505a7cf3945ca2ca690203010001a3533051301d0603551d0e0416041485478b7936ecd417647e9d8582d3f68fc670d839301f0603551d2304183016801485478b7936ecd417647e9d8582d3f68fc670d839300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003818100652656aef44c7a507a376de248cd1b36028fb1b0292593f88eb36b429f7de4c668aef7b0d862c9314e5d870f7c28353022657a7de07ec69505a54e48337ab6ba425bfd8865b720f1f2e86c92edaa261fd73e44856ac45c4d9378c86adb96b6f999f61e5f651cb885e06a3d909b5fa79458941bea36785ea585aeb5025032a18d"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate - Truncated within certificate list length",
+ input: "1603030acf0b000acb000a",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":2767,"truncated":true,"handshakeType":"certificate","certificateList":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate - Truncated before certificate list length",
+ input: "1603030acf0b000acb",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":2767,"truncated":true,"handshakeType":"certificate"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Key Exchange",
+ input: "16030300840c000080a90c12174921d7044303107b6e37523957439b436e57904e82702784bfc261a8f0a7e4143a77144357d29ee322f25e4fce393ac7570ee26c378298a6ad18fd8b87175e472c7c07b97699f72958e0af489df00d34e5e03dde2e09dfe06d448651ee45c07fadc05e0d1585589e3715a04b935e72bc28c34593712acef7883ed69a",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":132,"handshakeType":"server_key_exchange","handshakeValue":"0xa90c12174921d7044303107b6e37523957439b436e57904e82702784bfc261a8f0a7e4143a77144357d29ee322f25e4fce393ac7570ee26c378298a6ad18fd8b87175e472c7c07b97699f72958e0af489df00d34e5e03dde2e09dfe06d448651ee45c07fadc05e0d1585589e3715a04b935e72bc28c34593712acef7883ed69a"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Key Exchange - Truncated within content",
+ input: "16030300840c000080a90c12174921d7044303107b6e37523957439b436e57904e82702784bfc261a8f0a7e4143a77144357d29ee322f25e4fce393ac7570ee26c378298a6ad18fd8b",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":132,"truncated":true,"handshakeType":"server_key_exchange","handshakeValue":"0xa90c12174921d7044303107b6e37523957439b436e57904e82702784bfc261a8f0a7e4143a77144357d29ee322f25e4fce393ac7570ee26c378298a6ad18fd8b"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Key Exchange - Truncated before content",
+ input: "16030300840c000080",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":132,"truncated":true,"handshakeType":"server_key_exchange"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, No certificate authorities",
+ input: "160303001f0d00001b040102030400120601060206030301030203030201020202030000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":31,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202","0x0203"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities",
+ input: "16030300470d000043040102030400120601060206030301030203030201020202030028000c546bf13f358cf3ddc1eef77d001813b3cdd60a34fc74f2e4ef2344cfd2156924d8d2810e2c86",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202","0x0203"]},"certificateAuthorities":{"length":40,"values":["0x546bf13f358cf3ddc1eef77d","0x13b3cdd60a34fc74f2e4ef2344cfd2156924d8d2810e2c86"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated within certificate authority",
+ input: "16030300470d000043040102030400120601060206030301030203030201020202030028000c546bf13f358cf3ddc1eef77d001813b3cdd60a34fc74f2e4ef23",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202","0x0203"]},"certificateAuthorities":{"length":40,"truncated":true,"values":["0x546bf13f358cf3ddc1eef77d"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated before certificate authority",
+ input: "16030300470d000043040102030400120601060206030301030203030201020202030028000c546bf13f358cf3ddc1eef77d0018",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202","0x0203"]},"certificateAuthorities":{"length":40,"truncated":true,"values":["0x546bf13f358cf3ddc1eef77d"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated within certificate authority length",
+ input: "16030300470d000043040102030400120601060206030301030203030201020202030028000c546bf13f358cf3ddc1eef77d00",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202","0x0203"]},"certificateAuthorities":{"length":40,"truncated":true,"values":["0x546bf13f358cf3ddc1eef77d"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated before certificate authority length",
+ input: "16030300470d000043040102030400120601060206030301030203030201020202030028000c546bf13f358cf3ddc1eef77d",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202","0x0203"]},"certificateAuthorities":{"length":40,"truncated":true,"values":["0x546bf13f358cf3ddc1eef77d"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated within certificate authorities length",
+ input: "16030300470d0000430401020304001206010602060303010302030302010202020300",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202","0x0203"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated before certificate authorities length",
+ input: "16030300470d00004304010203040012060106020603030103020303020102020203",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202","0x0203"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated within supported signature algorithm",
+ input: "16030300470d000043040102030400120601060206030301030203030201020202",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"truncated":true,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated before supported signature algorithm",
+ input: "16030300470d0000430401020304001206010602060303010302030302010202",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{"length":18,"truncated":true,"values":["0x0601","0x0602","0x0603","0x0301","0x0302","0x0303","0x0201","0x0202"]}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated within supported signature algorithms length",
+ input: "16030300470d000043040102030400",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated before supported signature algorithms length",
+ input: "16030300470d0000430401020304",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"values":["0x01","0x02","0x03","0x04"]},"supportedSignatureAlgorithms":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated within certificate types",
+ input: "16030300470d00004304010203",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"truncated":true,"values":["0x01","0x02","0x03"]},"supportedSignatureAlgorithms":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated before certificate types",
+ input: "16030300470d00004304",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request","certificateTypes":{"length":4,"truncated":true,"values":[]},"supportedSignatureAlgorithms":{}}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Request, Certificate authorities - Truncated before certificate types length",
+ input: "16030300470d000043",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":71,"truncated":true,"handshakeType":"certificate_request"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Server Hello Done",
+ input: "16030300040e000000",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":4,"handshakeType":"server_hello_done"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Verify",
+ input: "16030301080f000104040101009310d3dda84b149a00258f0bb4501e710f7ed70a45cf4f0bab39dac1a456027f0f6167924f08a8221613bcf46c27e91458d05163200fd1bf3673351d74693c08c6640635d4e9f84e9568e39d3346e3ff2f3eacf9887d738935d8b07e42659dd3b212662bf028bcefe98b686a1a83fb2f24aead94cccd3f6b26c9d42ba43254d2a93d1b85ae2d0ee7c7170aac3397fa6de77183d30c99e6bb0e81f925793f64d8b490cb74d051896ebee9086c7606905b21bab6ebd9866a451958f7d839134aeb335b2ad5f9ce89a69321a099c081b5166332cf2bb231dd135b79cf94218e6ada94644eaa09ae6c0ec0164e3cca631c0f4b7b9a2d59fb40909ec88805e61b5917",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":264,"handshakeType":"certificate_verify","algorithmHash":"0x04","algorithmSignature":"0x01","signature":"0x9310d3dda84b149a00258f0bb4501e710f7ed70a45cf4f0bab39dac1a456027f0f6167924f08a8221613bcf46c27e91458d05163200fd1bf3673351d74693c08c6640635d4e9f84e9568e39d3346e3ff2f3eacf9887d738935d8b07e42659dd3b212662bf028bcefe98b686a1a83fb2f24aead94cccd3f6b26c9d42ba43254d2a93d1b85ae2d0ee7c7170aac3397fa6de77183d30c99e6bb0e81f925793f64d8b490cb74d051896ebee9086c7606905b21bab6ebd9866a451958f7d839134aeb335b2ad5f9ce89a69321a099c081b5166332cf2bb231dd135b79cf94218e6ada94644eaa09ae6c0ec0164e3cca631c0f4b7b9a2d59fb40909ec88805e61b5917"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Verify - Truncated within signature",
+ input: "16030301080f000104040101009310d3dda84b149a00258f0bb4501e710f7ed70a45cf4f0bab39dac1a456027f0f6167924f08a8221613bcf46c27e91458d05163200fd1bf3673351d74693c08c6640635d4e9f84e9568e39d3346e3ff2f3eacf9887d738935d8b07e42659dd3b212662bf028bcefe98b686a1a83fb2f24aead94cccd3f6b26c9d42ba43254d2",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":264,"truncated":true,"handshakeType":"certificate_verify","algorithmHash":"0x04","algorithmSignature":"0x01","signature":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Verify - Truncated before signature",
+ input: "16030301080f00010404010100",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":264,"truncated":true,"handshakeType":"certificate_verify","algorithmHash":"0x04","algorithmSignature":"0x01","signature":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Verify - Truncated within signature length",
+ input: "16030301080f000104040101",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":264,"truncated":true,"handshakeType":"certificate_verify","algorithmHash":"0x04","algorithmSignature":"0x01","signature":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Verify - Truncated before signature length",
+ input: "16030301080f0001040401",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":264,"truncated":true,"handshakeType":"certificate_verify","algorithmHash":"0x04","algorithmSignature":"0x01","signature":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Verify - Truncated before algorithm.signature",
+ input: "16030301080f00010404",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":264,"truncated":true,"handshakeType":"certificate_verify","algorithmHash":"0x04","algorithmSignature":"","signature":""}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Certificate Verify - Truncated before algorithm.hash",
+ input: "16030301080f000104",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":264,"truncated":true,"handshakeType":"certificate_verify"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Key Exchange",
+ input: "1603030084100000802b45af77539975e975c9389030193bb6d7841d870e058850a5aac5f8ded75d243ae8bec2bc8ba4e683eba22d5820b555c69f97001aa7d56cba1839588e7f1602ad0b4cb7319fc52694a67f1e381b4d8a581823410920717ee85ef352dea39097e6b131bdfeb3913f0f7eaa3b3882abe4615cc13e2a133558adff159771dfdc8d",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":132,"handshakeType":"client_key_exchange","handshakeValue":"0x2b45af77539975e975c9389030193bb6d7841d870e058850a5aac5f8ded75d243ae8bec2bc8ba4e683eba22d5820b555c69f97001aa7d56cba1839588e7f1602ad0b4cb7319fc52694a67f1e381b4d8a581823410920717ee85ef352dea39097e6b131bdfeb3913f0f7eaa3b3882abe4615cc13e2a133558adff159771dfdc8d"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Key Exchange - Truncated within content",
+ input: "1603030084100000802b45af77539975e975c9389030193bb6d7841d870e058850a5aac5f8ded75d243ae8bec2bc8ba4e683eba22d5820b555c69f97001aa7d56cba1839588e7f1602",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":132,"truncated":true,"handshakeType":"client_key_exchange","handshakeValue":"0x2b45af77539975e975c9389030193bb6d7841d870e058850a5aac5f8ded75d243ae8bec2bc8ba4e683eba22d5820b555c69f97001aa7d56cba1839588e7f1602"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Client Key Exchange - Truncated before content",
+ input: "160303008410000080",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":132,"truncated":true,"handshakeType":"client_key_exchange"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Finished",
+ input: "1603030028ed83078db91b046358065ca3f7ea4494af3deb59bf72f522e15ef9071c52becb0069a093b23994c1",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":40,"handshakeType":"finished","handshakeValue":"0xed83078db91b046358065ca3f7ea4494af3deb59bf72f522e15ef9071c52becb0069a093b23994c1"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Finished - Truncated within ciphertext",
+ input: "1603030028ed83078db91b046358065ca3f7ea4494af3deb59",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":40,"truncated":true,"handshakeType":"finished","handshakeValue":"0xed83078db91b046358065ca3f7ea4494af3deb59"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Unknown",
+ input: "1603030024120000203c210cd33fd2a7379ae02700b208ae7357f98b46a1dea566c4061acfb6e188bc",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":36,"handshakeType":"18","handshakeValue":"0x3c210cd33fd2a7379ae02700b208ae7357f98b46a1dea566c4061acfb6e188bc"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Unknown - Truncated within content",
+ input: "1603030024120000203c210cd33fd2a7379ae02700b208",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":36,"truncated":true,"handshakeType":"18","handshakeValue":"0x3c210cd33fd2a7379ae02700b208"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Handshake - Unknown - Truncated before content",
+ input: "160303002412000020",
+ expectedOutput: '[{"type":"handshake","version":"0x0303","length":36,"truncated":true,"handshakeType":"18"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Application Data",
+ input: "1703030064bbfd70f5d2ae0fe62262830040c264fa578bf2000ea50bb2c92d4837727f5db06b580e43896eaa1a0042b4fc3eb5aca6731705f5d957c481bade800cf1cd066dfd997851af09e820e84ee0b531b4eaccfd8b5f28b74d756a8aeadf78eefb2d26e46b5b69",
+ expectedOutput: '[{"type":"application_data","version":"0x0303","length":100,"value":"0xbbfd70f5d2ae0fe62262830040c264fa578bf2000ea50bb2c92d4837727f5db06b580e43896eaa1a0042b4fc3eb5aca6731705f5d957c481bade800cf1cd066dfd997851af09e820e84ee0b531b4eaccfd8b5f28b74d756a8aeadf78eefb2d26e46b5b69"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Application Data - Truncated within content",
+ input: "1703030064bbfd70f5d2ae0fe62262830040c264fa578bf2000ea50bb2c92d4837727f5db06b580e43896eaa1a0042b4fc3eb5aca67317",
+ expectedOutput: '[{"type":"application_data","version":"0x0303","length":100,"truncated":true,"value":"0xbbfd70f5d2ae0fe62262830040c264fa578bf2000ea50bb2c92d4837727f5db06b580e43896eaa1a0042b4fc3eb5aca67317"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Application Data - Truncated before content",
+ input: "1703030064",
+ expectedOutput: '[{"type":"application_data","version":"0x0303","length":100,"truncated":true}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Unknown",
+ input: "1c03030020c02beaae1dd2e9ec46c4d201d72105457af1f8e92d56ad95f339398e5774cb6f",
+ expectedOutput: '[{"type":"28","version":"0x0303","length":32,"value":"0xc02beaae1dd2e9ec46c4d201d72105457af1f8e92d56ad95f339398e5774cb6f"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Unknown - Truncated within content",
+ input: "1c03030020c02beaae1dd2e9ec46c4d201d7210545",
+ expectedOutput: '[{"type":"28","version":"0x0303","length":32,"truncated":true,"value":"0xc02beaae1dd2e9ec46c4d201d7210545"}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ },
+ {
+ name: "Parse TLS record: Unknown - Truncated before content",
+ input: "1c03030020",
+ expectedOutput: '[{"type":"28","version":"0x0303","length":32,"truncated":true}]',
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"]
+ },
+ {
+ op: "Parse TLS record",
+ args: []
+ },
+ {
+ op: "JSON Minify",
+ args: []
+ }
+ ]
+ }
+]);