3.0 KiB
public/serialize — TPMT_PUBLIC canonical serialiser
Purpose
serializeTpmtPublic re-emits a parsed TpmtPublic value as the
TCG-canonical byte string per Library Part 2 §12.2. It is the
round-trip partner of parseTpmtPublic: for any input the parser
accepts, serialize(parse(bytes)) returns the same bytes. This
property is load-bearing — computeTpmtPublicName per Part 1 §16
hashes the canonical bytes to produce the TPM name digest, and any
mismatch between the parser and the serialiser would silently produce a
wrong name, which in turn would silently fail every downstream
attestation check.
Features
- Byte-identical round-trip across RSA, ECC, KEYEDHASH, and SYMCIPHER branches.
- Preserves
rawExponent(default-exponent normalisation is a parse-time convenience; the wire bytes are emitted unchanged). - Re-writes every
TPM2B_*size prefix from the decoded payload length — the serialiser never trusts a stored size value. - Schema-validated input via the public API: only outputs of
parseTpmtPublic(which are validated) can reach the serialiser.
Usage: Basic Example
import {
parseTpmtPublic,
serializeTpmtPublic,
} from "@suaveplan/tpm-struct/public";
const pub = parseTpmtPublic(bytes);
const reSerialised = serializeTpmtPublic(pub);
// reSerialised equals bytes byte-for-byte.
Usage: Advanced Example
import {
parseTpmtPublic,
serializeTpmtPublic,
} from "@suaveplan/tpm-struct/public";
// Re-emit pub-area bytes through the canonical serialiser before signing
// or hashing. This is the canonical witness for TCG TPM 2.0 Library
// Part 1 §16 name computation.
function canonicalPubArea(rawPubArea: Uint8Array): Uint8Array {
return serializeTpmtPublic(parseTpmtPublic(rawPubArea));
}
// Property test pattern used by `property.test.ts`:
import fc from "fast-check";
fc.assert(
fc.property(fc.uint8Array({ maxLength: 600 }), (bytes) => {
// Parsing might throw; that is expected for invalid inputs.
// The serialiser is exercised only on parse-success paths.
let parsed;
try {
parsed = parseTpmtPublic(bytes);
} catch {
return true;
}
return serializeTpmtPublic(parsed).join() === bytes.join();
}),
{ numRuns: 100 }
);
API Reference
serializeTpmtPublic(pub: TpmtPublic): Uint8Array— returns a fresh byte string. ThrowsTpmStructError(PARAMETERS_INVALID)if a parameter substructure is internally inconsistent (e.g. non-NULL RSA scheme withouthashAlg).
Implementation Notes
The serialiser dispatches on pub.type and walks the §12.2 field order.
The symmetric / scheme / KDF sub-writers each consult their algorithm
discriminator to decide whether trailing fields are emitted (e.g. an RSA
scheme of TPM_ALG_NULL emits only the 2-byte scheme id and no hashAlg).
This mirrors how the parser reads those substructures and is what makes
the round-trip property hold across the full input space.