From 745ea5cba2880aea0d7d21b5c0035c6168103ba8 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Tue, 1 Sep 2026 10:35:44 +0200 Subject: [PATCH] bip-85: add example use for age key derivation Documents the connection between BIP-85's HEX application output at num_bytes=32 and the private-key seed format used by the age file-encryption format (https://age-encryption.org/v1) for both the classic X25519 identity (since age v1.0) and the post-quantum X-Wing identity (age v1.3.0+, Dec 2024). No new application number, no normative MUSTs added, no changes required in existing implementations. The amendment is purely documentational: a single subsection appended at the end of the HEX section. A test vector is added using the same master xprv as the existing HEX test vector in the same section, with both classic and post-quantum outputs. The PQ recipient (a ~1959-character bech32 string encoding the 1216-byte X-Wing public key) is included as a SHA-256 hash inline; the full string is in the reference implementation's test data. Reference implementation: https://github.com/dmonakhov/age-keygen-det - single-binary Go tool, BSD-3-Clause - cross-validates byte-for-byte against stock age-keygen -y in CI for both flavours --- bip-0085.mediawiki | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/bip-0085.mediawiki b/bip-0085.mediawiki index b0f00abbef..547e5e8dfc 100644 --- a/bip-0085.mediawiki +++ b/bip-0085.mediawiki @@ -282,6 +282,47 @@ INPUT: OUTPUT * DERIVED ENTROPY=492db4698cf3b73a5a24998aa3e9d7fa96275d85724a91e71aa2d645442f878555d078fd1f1f67e368976f04137b1f7a0d19232136ca50c44614af72b5582a5c +====age file encryption keys==== + +A 32-byte HEX-application output at m/83696968'/128169'/32'/{index}' is a +cryptographically random value usable directly as the secret key of an +[https://age-encryption.org/v1 age] file-encryption identity. age has two identity flavors. +Both encode a 32-byte seed. The matching recipient (public key) is derived from the seed as follows: + +{| class="wikitable" +! Flavor !! Role !! HRP !! Bech32-encoded payload +|- +| classic (X25519) || identity || AGE-SECRET-KEY- || 32-byte seed +|- +| classic (X25519) || recipient || age || X25519(seed, G), 32 bytes +|- +| post-quantum (X-Wing) || identity || AGE-SECRET-KEY-PQ- || 32-byte seed +|- +| post-quantum (X-Wing) || recipient || age1pq || X-Wing encapsulation key, 1216 bytes +|} + +A given index SHOULD be used with only one flavor: a cryptographically-relevant quantum computer +could recover the seed from the published classic recipient X25519(seed, G) and +thereby also compromise the post-quantum identity derived from the same seed. + +Every string above takes the form HRP || "1" || encode(payload) || checksum, using the +Bech32 (BIP-173) character set and checksum but without Bech32's 90-character length limit. +G is the Curve25519 base point, so X25519(seed, G) is the classic +recipient's public key. For the post-quantum flavor (age v1.3.0+), X-Wing SHAKE256-expands the +seed into its ML-KEM-768 and X25519 components, and the recipient encodes the resulting +1216-byte X-Wing encapsulation key. + +INPUT: +* MASTER BIP32 ROOT KEY: xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb +* PATH: m/83696968'/128169'/32'/0' + +OUTPUT: +* DERIVED ENTROPY=ea3ceb0b02ee8e587779c63f4b7b3a21e950a213f1ec53cab608d13e8796e6dc +* DERIVED AGE IDENTITY (classic)=AGE-SECRET-KEY-1AG7WKZCZA689SAMECCL5K7E6Y854PGSN78K98J4KPRGNAPUKUMWQWNNT4U +* DERIVED AGE RECIPIENT (classic)=age1m0hhzxelxsxnxm4ennvdpk75j8s7mn5w4tt3e4ntug5qx256wslqmdz8e9 +* DERIVED AGE IDENTITY (PQ)=AGE-SECRET-KEY-PQ-1AG7WKZCZA689SAMECCL5K7E6Y854PGSN78K98J4KPRGNAPUKUMWQ5AN2M5 +* DERIVED AGE RECIPIENT (PQ) SHA-256 (of the 1959-char bech32 string, no trailing newline)=855bd04ee0cd6cfdf5717fb946d859824a79fbbdf6304dadcc11dbb91abe0df6 + ===PWD BASE64=== Application number: 707764'