Loading vLEI.wiki
Fetching knowledge base...
Fetching knowledge base...
This comprehensive explanation has been generated from 66 GitHub source documents. All source documents are searchable here.
Last updated: October 7, 2025
This content is meant to be consumed by AI agents via MCP. Click here to get the MCP configuration.
Note: In rare cases it may contain LLM hallucinations.
For authoritative documentation, please consult the official GLEIF vLEI trainings and the ToIP Glossary.
A derivation code is a compact, prepended character sequence in CESR encoding that specifies the cryptographic algorithm, key type, or operation used to derive a cryptographic primitive, enabling self-describing, composable representations of keys, digests, and signatures without external schema information.
A derivation code is a prepended metadata indicator in KERI's Composable Event Streaming Representation (CESR) that encodes the cryptographic algorithm, key type, digest function, or signature scheme used to generate a cryptographic primitive. This code transforms raw cryptographic material into a qualified primitive that is self-describing and independently verifiable.
Formally, a derivation code is a fixed-length character sequence (in text domain) or byte sequence (in binary domain) that:
Derivation codes solve a fundamental problem in cryptographic systems: how to know which algorithm was used to generate a piece of cryptographic material. When a verifier receives a public key, signature, or digest, they must know:
Implementations MUST maintain accurate code tables mapping derivation codes to algorithm specifications. The CESR specification defines multiple tables that must be synchronized:
Code tables must specify for each code:
All CESR primitives MUST maintain 24-bit boundary alignment:
Pad size calculation: ps = (3 - (N mod 3)) mod 3 where N is raw byte length.
Implement cold start parsing capability:
Do NOT attempt to parse primitives with unknown derivation codes—reject immediately.
Unknown Codes: Reject primitives with unrecognized derivation codes. Do not attempt to parse or skip.
Length Mismatches: If extracted primitive length doesn't match code specification, reject as corrupted.
Invalid Base64: If Base64 decoding fails, reject primitive and indicate encoding error.
Design code table systems to support:
Traditional systems solve this through:
KERI's derivation codes embed this information directly in the identifier or primitive itself, creating truly portable, self-contained cryptographic objects.
Derivation codes are classified into three primary categories in CESR:
Derivation codes do not perform cryptographic operations themselves—they are metadata indicators that specify which algorithms were used. Common derivation codes include:
Public Key Algorithms:
B: Ed25519 non-transferable prefix public verification key (44 characters)D: Ed25519 public verification key (44 characters)1AAA: ECDSA secp256k1 non-transferable prefix (48 characters)1AAC: Ed448 non-transferable prefix (80 characters)Digest Algorithms:
E: Blake3-256 digest (44 characters)F: Blake2b-256 digest (44 characters)H: SHA3-256 digest (44 characters)I: SHA2-256 digest (44 characters)0D: Blake3-512 digest (88 characters)0F: SHA3-512 digest (88 characters)Signature Algorithms:
0B: Ed25519 signature (88 characters)0C: ECDSA secp256k1 signature (88 characters)1AAE: Ed448 signature (152 characters)Derivation codes themselves provide no cryptographic security—they are plaintext metadata. However, they enable critical security properties:
Cryptographic Agility: Systems can support multiple algorithms simultaneously without breaking changes. New algorithms can be added by defining new derivation codes.
Algorithm Binding: The derivation code creates an immutable binding between the algorithm specification and the cryptographic material. Changing the code invalidates the primitive.
Verification Determinism: Verifiers can deterministically select the correct algorithm without ambiguity or negotiation.
Post-Quantum Readiness: New post-quantum algorithms can be integrated by defining new derivation codes without protocol changes.
Derivation codes implicitly encode the expected size of cryptographic material:
Single-character codes (e.g., B, E, F):
Two-character codes (e.g., 0B, 0D, 0F):
Four-character codes (e.g., 1AAA, 1AAC):
The 24-bit alignment constraint is fundamental: all CESR primitives must be integer multiples of 4 Base64 characters (24 bits) in text domain and 3 bytes (24 bits) in binary domain. This ensures composability—the ability to convert concatenated primitives between domains without losing structure.
CESR encoding transforms raw cryptographic material into qualified primitives through a precise process:
Step 1: Determine Pad Size
Given raw material of N bytes, calculate pad size:
ps = (3 - (N mod 3)) mod 3
For a 32-byte Ed25519 public key:
ps = (3 - (32 mod 3)) mod 3 = (3 - 2) mod 3 = 1
Step 2: Prepend Lead Bytes
Prepend ps zero bytes to the raw material:
padded = [0x00] * ps + raw_bytes
For 32-byte key with ps=1:
padded = [0x00] + [32 bytes of key material] = 33 bytes
Step 3: Base64 Encode
Encode the padded bytes using Base64 URL-safe encoding:
encoded = base64_url_safe_encode(padded)
This produces 44 characters (33 bytes * 8 bits / 6 bits per Base64 char = 44).
Step 4: Replace Lead Characters with Derivation Code
The first ps Base64 characters result from the lead bytes and contain no information from the raw material. Replace these with the derivation code:
qualified = derivation_code + encoded[ps:]
For Ed25519 with code B:
qualified = 'B' + encoded[1:] = 'BF5pxRJP6THrUtlDdhh07hJEDKrJxkcR9m5u1xs33bhp'
Text Domain (T):
[A-Z, a-z, 0-9, -, _]BF5pxRJP6THrUtlDdhh07hJEDKrJxkcR9m5u1xs33bhpBinary Domain (B):
[0x04, 0x17, 0xa7, ...] (33 bytes total)Raw Domain (R):
(derivation_code, raw_bytes)('B', [0x17, 0xa7, 0x1c, ...]) (32 raw bytes)Derivation codes follow specific structural patterns:
Single-character codes (most common):
B, D, E, F, H, ITwo-character codes (larger primitives):
0 (zero)0B, 0D, 0E, 0F, 0GFour-character codes (specialized algorithms):
1 (one)1AAA, 1AAB, 1AAC, 1AAD, 1AAEInception Events (icp):
Derivation codes appear in multiple fields:
{
"v": "KERI10JSON000188_",
"t": "icp",
"d": "ELvaU6Z-i0d8JJR2nmwyYAZAoTNZH3UfSVPzhzS6b5CM",
"i": "ELvaU6Z-i0d8JJR2nmwyYAZAoTNZH3UfSVPzhzS6b5CM",
"s": "0",
"kt": "1",
"k": ["DKrJxkcR9m5u1xs33F5pxRJP6T7hJEbhpHrUtlDdhh0"],
"n": ["ELvaU6Z-i0d8JJR2nmwyYAZAoTNZH3UfSVPzhzS6b5CM"]
}
d field: SAID with E derivation code (Blake3-256 digest)i field: AID prefix with E code (self-addressing identifier)k array: Current signing key with D code (Ed25519 public key)n array: Next key digest with E code (Blake3-256 of pre-rotated key)Rotation Events (rot):
Similar structure with updated keys:
{
"v": "KERI10JSON000190_",
"t": "rot",
"d": "EY6jnekRK0M3GzKd7N0xH6fMJk2EqPjLkEcvXqhJRkqw",
"i": "ELvaU6Z-i0d8JJR2nmwyYAZAoTNZH3UfSVPzhzS6b5CM",
"s": "1",
"p": "ELvaU6Z-i0d8JJR2nmwyYAZAoTNZH3UfSVPzhzS6b5CM",
"kt": "1",
"k": ["DNewKeyMaterialAfterRotation123456789012345678"],
"n": ["ENextKeyDigestForSubsequentRotation1234567890"]
}
p field: Prior event digest with E codek and n values with appropriate derivation codesInteraction Events (ixn):
Minimal structure for anchoring:
{
"v": "KERI10JSON000138_",
"t": "ixn",
"d": "EAnchoredDataDigest123456789012345678901234",
"i": "ELvaU6Z-i0d8JJR2nmwyYAZAoTNZH3UfSVPzhzS6b5CM",
"s": "2",
"p": "EY6jnekRK0M3GzKd7N0xH6fMJk2EqPjLkEcvXqhJRkqw",
"a": ["ESealedDataDigest1234567890123456789012345"]
}
a array: Anchored data seals with E codesSelf-Certifying Identifiers:
The most fundamental usage is in AID prefixes:
BF5pxRJP6THrUtlDdhh07hJEDKrJxkcR9m5u1xs33bhp
Breakdown:
B: Derivation code indicating Ed25519 non-transferableF5pxRJP6THrUtlDdhh07hJEDKrJxkcR9m5u1xs33bhp: Base64-encoded public keyVerification process:
BSelf-Addressing Identifiers:
For self-addressing AIDs:
ELvaU6Z-i0d8JJR2nmwyYAZAoTNZH3UfSVPzhzS6b5CM
Breakdown:
E: Derivation code indicating Blake3-256 digestLvaU6Z-i0d8JJR2nmwyYAZAoTNZH3UfSVPzhzS6b5CM: Base64-encoded digestVerification process:
Ei field with dummy charactersWitness Receipts:
Witness signatures use indexed signature codes:
-CAB
0BAAAAAAAAAAAAAAAAAAAAAA
BJq7UABlttINuWJh1Xl2lkqZG4NTdUdqnbFJDa6ZyxCC
0BSignatureBytes1234567890123456789012345678901234567890123456789012345678901234
Breakdown:
-CAB: Count code indicating 2 indexed signatures follow0B: Indexed signature derivation code (Ed25519)Public Key Verification:
Digest Verification:
SAID Verification:
# charactersDerivation codes qualify various types of cryptographic material:
Keys: Public keys (B, D, 1AAA), private keys (A, J), encryption keys (C, O)
Digests: Hash outputs (E, F, G, H, I, 0D, 0E, 0F, 0G)
Signatures: Signature values (0B, 0C, 1AAE)
Salts/Seeds: Random values (0A, A)
For multi-signature scenarios, derivation codes include index information:
Siger (indexed signature): Combines signature with index indicating which key signed
Cigar (un-indexed signature): Signature without index for single-sig scenarios
Both use the same underlying derivation codes but with different framing.
Special derivation codes indicate groups of primitives:
-CAB: Count code for 2 indexed signatures
-CAC: Count code for 3 indexed signatures
-GAB: Group code for event source seals
These enable pipelined streaming where multiple primitives are processed as a unit.
Concatenated Streams:
Multiple qualified primitives can be concatenated:
BKey1234567890123456789012345678901234567890EDigest1234567890123456789012345678901234560BSignature123456789012345678901234567890123456789012345678901234567890123456789012
Parsing:
B → 44-character Ed25519 key followsE → 44-character Blake3-256 digest follows0B → 88-character Ed25519 signature followsNested Structures:
ACDC credentials contain multiple qualified primitives:
{
"v": "ACDC10JSON000197_",
"d": "ECredentialSAID1234567890123456789012345",
"i": "EIssuerAID123456789012345678901234567890",
"s": "ESchemaID1234567890123456789012345678901",
"a": {
"d": "EAttributeBlockSAID123456789012345678901",
"name": "Alice"
}
}
Each d, i, s field contains a qualified primitive with derivation code.
Implementations must maintain code tables mapping derivation codes to:
The CESR specification defines multiple code tables:
Small Fixed Raw Size Table: Single-character codes for 32-byte primitives Large Fixed Raw Size Table: Two-character codes for 64-byte primitives Variable Raw Size Tables: Four-character codes for variable-length primitives
Cold Start Parsing:
When beginning to parse a CESR stream:
Stream Processing:
For continuous streams:
Unknown Codes:
If a derivation code is not recognized:
Length Mismatches:
If primitive length doesn't match code specification:
Invalid Base64:
If Base64 decoding fails:
Code Lookup:
Use hash tables or switch statements for O(1) code lookup:
CODE_TABLE = {
'B': {'algorithm': 'Ed25519', 'length': 44, 'pad': 1},
'E': {'algorithm': 'Blake3-256', 'length': 44, 'pad': 1},
'0B': {'algorithm': 'Ed25519-Sig', 'length': 88, 'pad': 2},
# ...
}
Batch Processing:
Process groups of primitives together when count codes indicate batches:
if code == '-CAB': # 2 indexed signatures
signatures = parse_batch(stream, count=2, type='indexed_sig')
verify_batch(signatures)
Zero-Copy Parsing:
Where possible, avoid copying data:
# Instead of:
key_bytes = stream[1:44].decode('base64')
# Use views:
key_view = memoryview(stream)[1:44]
Derivation codes enable seamless algorithm upgrades:
Adding New Algorithms:
Deprecating Algorithms:
Post-Quantum Transition:
When quantum computers threaten current algorithms:
This approach ensures KERI remains secure even as cryptographic landscape evolves.
Code Lookup: Use hash tables or switch statements for O(1) derivation code lookup.
Batch Processing: When count codes indicate groups, process primitives in batches for efficiency.
Zero-Copy Parsing: Where possible, use memory views to avoid copying data during parsing.
Algorithm Binding: The derivation code creates an immutable binding between algorithm specification and cryptographic material. Changing the code invalidates the primitive.
Verification Determinism: Always use the algorithm specified by the derivation code—never substitute or negotiate alternatives.
Deprecation Policy: Continue supporting deprecated codes for verification of historical data, but prevent new issuance.
Implementations should test:
All KERI implementations MUST:
This ensures that KERI identifiers and events are portable across implementations.