← Book map

Chapter 04 · Foundations

A signature that explains itself

A raw signature is ambiguous in a system where the same 20 bytes can mean different things under different keys. The verifiable container removes the ambiguity.

What VerifiableSignatureData carries A verifiable signature bundles the signature bytes with the identity, system, hash type, and optional vdxf keys, key names, bound hashes and statements. VerifiableSignatureData — flags 1 · 2 · 4 · 8 · 16 identity + system who, on which chain hash type sha256 / sha256d vdxf keys what is being signed signature bytes DER, no key material OPTIONAL BINDINGS bound hashes — pin the signature to specific data statements — signed assertions beyond the envelope vdxf key names — human-readable key provenance The verifier checks these, not the transport.

FIGURE 4.1 · The self-describing signature container.

Why not just a signature string

A raw signature says "someone with this key signed these bytes". It does not say which identity, which chain, which hash function, or which VDXF keys the signer intended. In a system where the same 20-byte payload can mean different things under different keys, that ambiguity is an attack surface.

VerifiableSignatureData makes the signature self-describing: identity and system as compact addresses, a hash type, the signature version, optional key list, optional bound hashes, optional statements, and the signature bytes. A verifier can reconstruct the exact message without trusting the transport to have preserved context.

The flags you will actually meet

FlagValueMeans
FLAG_HAS_VDXF_KEYS1A list of vdxf keys qualifies the signature
FLAG_HAS_VDXF_KEY_NAMES2Those keys also carry their names
FLAG_HAS_BOUND_HASHES4Signature is bound to specific hashes
FLAG_HAS_STATEMENTS8Additional signed statements
FLAG_HAS_SYSTEM16A non-default system chain is named

Where it plugs in

GenericEnvelope.signature is a VerifiableSignatureData, and FLAG_SIGNED on the envelope is what tells the reader to parse it. The signature covers the envelope's own hash — which is why changing details after signing invalidates it, and why createdAt and salt participate in uniqueness.

Sign the bytes you will send. Serialising, then re-serialising with a different field order or a refreshed timestamp, produces a signature that is valid for a message nobody received.

Reading the code

src/vdxf/classes/VerifiableSignatureData.ts
  toBuffer / fromBuffer       # flags, version, sigversion, hashtype, compact ids
  toJson / fromJson           # vdxfkeys, vdxfkeynames, boundhashes, statements
  fromCLIJson                 # adapts `verus signdata` output
src/pbaas/SignatureData.ts    # the underlying DER signature container