Loading vLEI.wiki
Fetching knowledge base...
Fetching knowledge base...
This comprehensive explanation has been generated from 3 GitHub source documents. All source documents are searchable here.
Last updated: September 21, 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.
Hierarchical Deterministic Keys (HDK) are cryptographic key derivation systems that generate child keys from parent keys using deterministic algorithms and chain codes, enabling the creation of unlimited key pairs from a single seed while maintaining cryptographic relationships invisible to parties without the seed.
Hierarchical Deterministic Keys (HDK) represent a cryptographic key management system that enables the deterministic generation of child key pairs from parent key pairs using a combination of cryptographic hash functions and chain codes. The system is formally defined by BIP-32 (Bitcoin Improvement Proposal 32) and provides a mathematically deterministic method for creating an unlimited number of cryptographically related key pairs from a single root seed.
The fundamental mathematical relationship can be expressed as:
child_key = HMAC-SHA512(parent_key || chain_code || index)
Where || represents concatenation, and the resulting 512-bit output is split into a 256-bit private key and 256-bit chain code for the child.
Extended Keys (xprv/xpub):
Secure Random Number Generation:
Memory Protection:
// Secure memory allocation for private keys
void* secure_alloc(size_t size) {
void* ptr = mlock(malloc(size), size); // Lock pages in memory
if (!ptr) handle_allocation_error();
return ptr;
}
void secure_free(void* ptr, size_t size) {
explicit_bzero(ptr, size); // Zero memory before free
munlock(ptr, size); // Unlock pages
free(ptr);
}
Constant-Time Operations:
Precomputed Tables:
Batch Operations:
def batch_derive_keys(parent_key: bytes, chain_code: bytes,
indices: list[int]) -> list[tuple[bytes, bytes]]:
"""Efficiently derive multiple child keys"""
results = []
# Sort indices to optimize cache usage
sorted_indices = sorted(indices)
for index in sorted_indices:
child_key, child_chain = derive_child_key(parent_key, chain_code, index)
results.append((child_key, child_chain))
return results
Caching Strategies:
Invalid Key Handling:
Total Extended Key Size: 78 bytes (111 characters in Base58Check encoding)
Derivation Path Format:
m / purpose' / coin_type' / account' / change / address_index
m: Master key': Hardened derivation (adds 2^31 to index)/: Path separatorMaster Key Generation:
I = HMAC-SHA512("Bitcoin seed", seed)IL (left 256 bits): Master private keyIR (right 256 bits): Master chain codeIL is valid (0 < IL < curve order n)Child Key Derivation (Non-Hardened):
def derive_child_key(parent_key, parent_chain_code, index):
if index >= 2**31: # Hardened derivation
data = b'\x00' + parent_key + index.to_bytes(4, 'big')
else: # Non-hardened derivation
data = public_key_from_private(parent_key) + index.to_bytes(4, 'big')
I = hmac.new(parent_chain_code, data, hashlib.sha512).digest()
IL, IR = I[:32], I[32:]
child_key = (int.from_bytes(IL, 'big') + int.from_bytes(parent_key, 'big')) % CURVE_ORDER
child_chain_code = IR
return child_key.to_bytes(32, 'big'), child_chain_code
Public Key Derivation: Non-hardened derivation allows public key derivation without private keys:
child_pubkey = parent_pubkey + IL * G
Where G is the generator point of the elliptic curve.
Elliptic Curve Parameters (secp256k1):
Security Properties:
Hardened vs Non-Hardened Derivation:
Core HDK Interface:
interface HDKNode {
readonly privateKey?: Uint8Array; // 32 bytes, optional for public-only nodes
readonly publicKey: Uint8Array; // 33 bytes compressed
readonly chainCode: Uint8Array; // 32 bytes
readonly depth: number; // 0-255
readonly index: number; // 0 to 2^32-1
readonly parentFingerprint: number; // 32-bit identifier
derive(index: number): HDKNode;
deriveHardened(index: number): HDKNode;
derivePath(path: string): HDKNode;
toExtendedKey(): string; // Base58Check encoded
getAddress(): string; // Address derivation
}
Derivation Methods:
class HDKImplementation {
static fromSeed(seed: Uint8Array): HDKNode {
const I = hmac(sha512, "Bitcoin seed", seed);
const IL = I.slice(0, 32);
const IR = I.slice(32, 64);
if (!isValidPrivateKey(IL)) {
throw new Error("Invalid seed");
}
return new HDKNode({
privateKey: IL,
chainCode: IR,
depth: 0,
index: 0,
parentFingerprint: 0
});
}
static fromExtendedKey(xkey: string): HDKNode {
const decoded = base58check.decode(xkey);
// Parse 78-byte extended key format
return parseExtendedKey(decoded);
}
}
Memory Management:
Concurrency Model:
Performance Optimizations:
KERI Integration:
class KERIHDKManager:
def __init__(self, seed: bytes, salt: str = "KERI"):
self.root = HDK.from_seed(hmac_sha512(salt.encode(), seed))
self.aid_path = "m/0'/0'" # AID derivation path
self.signing_path = "m/0'/1'" # Signing key path
self.rotation_path = "m/0'/2'" # Pre-rotation key path
def derive_aid_keys(self, aid_index: int) -> Tuple[bytes, bytes]:
"""Derive current and next keys for AID"""
current = self.root.derive_path(f"{self.aid_path}/{aid_index}")
next_key = self.root.derive_path(f"{self.rotation_path}/{aid_index}")
return current.private_key, next_key.private_key
def derive_signing_keys(self, aid_index: int, key_index: int) -> bytes:
"""Derive signing keys for specific AID and key index"""
path = f"{self.signing_path}/{aid_index}/{key_index}"
return self.root.derive_path(path).private_key
Configuration Parameters:
KERI Integration Points:
ACDC Integration:
CESR Encoding:
# HDK-derived keys in CESR format
def encode_hdk_key(derived_key: HDKNode, derivation_path: str) -> str:
"""Encode HDK-derived key with derivation metadata"""
key_data = derived_key.public_key
path_hash = blake3(derivation_path.encode()).digest()[:4]
# CESR encoding with HDK-specific derivation code
return cesr_encode("HDK", key_data + path_hash)
Computational Complexity:
Memory Footprint:
Performance Benchmarks (Intel i7-10700K):
Network Overhead:
Invalid Key Detection:
def is_valid_private_key(key: bytes) -> bool:
"""Validate private key is within curve order"""
if len(key) != 32:
return False
key_int = int.from_bytes(key, 'big')
return 0 < key_int < SECP256K1_ORDER
def handle_invalid_derivation(parent_key: bytes, index: int) -> bytes:
"""Handle invalid child key derivation"""
attempt = 0
while attempt < 2**32:
try:
child_key = derive_child_key(parent_key, index + attempt)
if is_valid_private_key(child_key):
return child_key
except InvalidKeyError:
attempt += 1
raise DerivationError("Unable to derive valid key")
Boundary Conditions:
Security Considerations:
Primary Standards:
Cryptographic Standards:
Version History:
Deployment Architectures:
Monitoring & Observability:
Operational Procedures:
Scaling Strategies:
Path Validation:
def validate_derivation_path(path: str) -> list[int]:
"""Validate and parse BIP-32 derivation path"""
if not path.startswith('m/'):
raise ValueError("Path must start with 'm/'")
components = path[2:].split('/')
indices = []
for component in components:
if component.endswith("'"):
# Hardened derivation
index = int(component[:-1]) + 2**31
else:
index = int(component)
if index >= 2**32:
raise ValueError(f"Index {index} exceeds 32-bit limit")
indices.append(index)
if len(indices) > 255:
raise ValueError("Derivation path too deep (max 255 levels)")
return indices
Endianness Issues:
Test Vector Validation:
Property-Based Testing:
@given(st.binary(min_size=16, max_size=64))
def test_master_key_generation(seed):
"""Property-based test for master key generation"""
master_key, chain_code = generate_master_key(seed)
# Properties that should always hold
assert len(master_key) == 32
assert len(chain_code) == 32
assert int.from_bytes(master_key, 'big') < SECP256K1_ORDER
assert int.from_bytes(master_key, 'big') > 0
Security Testing:
Integration Testing: