tags | |
---|---|
KERI |
KERI's rotation mechanism involves committing to the next Key Configuration while you rotate from the previous Configuration to the current Configuration. This commitment is a digest of the Configuration, such that the Public Keys in the Configuration are hidden. Finally, the Rotation event which changes these keys must be signed by the keys which were previously in the commitment and are now revealed in the event. This Pre-Rotation scheme is designed to:
- Commit to the next key set in advance, to prevent malicious rotation
- Enforce rotation-on-first-use, such that the controlling key set is always kept as secure as possible
- Conceal the next key set, to mitigate potential risks from broken public key cryptography schemes or quantum computing attacks
- Conceal the keys used to assemble the commitment while they're being collected
The Key Configuration used to generate nxt
consists of two elements:
- The Signature Threshold, or
sith
: integer or set of integers describing how many signatures are required from keys in the set, for Events to be considered properly signed, serialized as a plain hex string. - The Keys (
keys
): the set of Public Keys used to verify the signatures on Events, serialized in fully-qualified prefix form.
Example:
{
"sith": "2",
"keys": [
"BrHLayDN-mXKv62DAjFLX1_Y5yEUe0vA9YPe_ihiKYHE",
"BujP_71bmWFVcvFmkE9uS8BTZ54GIstZ20nj_UloF8Rk",
"B8T4xkb8En6o0Uo5ZImco1_08gT5zcYnXzizUPVNzicw"
]
}
In order to commit to the configuration, each of the elements must be combined in a cryptographic digest. The process for this is as follows:
- Choose a method
D
from the set of self-addressing derivation methods - Encode the
sith
integer as a hex string (lower-case, no leading zeros or0x
) - Encode all
keys
in their serialized prefix form - Get
sith_d
fromD(sith)
- For each
key_n
inkeys
, getkey_n_d
fromD(key_n)
to create the set of digestsdigests
- For
sith_d
and each elementd
indigests
, get the raw bytes of the digest (without the derivation code) and XOR them all together to makexor_raw
- Serialize
xor_raw
to base64 URL safe form without padding and prepend the derivation code ofD
In contrast to a simple concatenate-and-digest approach, the XOR method has two advantages:
- Public Keys to create the config can be passed around outside of trusted or secure infrastructure to create the
nxt
commitment without being intercepted, as they can be hashed and concealed prior to transmission. - The order of processing of the elements does not need to be consistent as XOR is commutative, unlike concatenation.
The following example shows the nxt creation process in Python:.
sith = 2
keys = ['BrHLayDN-mXKv62DAjFLX1_Y5yEUe0vA9YPe_ihiKYHE',
'BujP_71bmWFVcvFmkE9uS8BTZ54GIstZ20nj_UloF8Rk',
'B8T4xkb8En6o0Uo5ZImco1_08gT5zcYnXzizUPVNzicw']
# convert sith to hex string no leading zeros
sith = '2'
# Blake3_256 sith digest, fully qualified prefix form
sithdig = 'EgT6bcpFB5_OFr6Ci0N8-bDeJ5Cf_5K7vVmpWW8jy_j0'
# raw binary unqualified in string escaped form
sithdig == b"\x81>\x9br\x91A\xe7\xf3\x85\xaf\xa0\xa2\xd0\xdf>l7\x89\xe4'\xff\xe4\xae\xefVjV[\xc8\xf2\xfe="
# convert keys to digests
# fully qualified Base64 digests
keydigs == ['EmB26yMzroICh-opKNdkYyP000kwevU18WQI95JaJDjY',
'EO4CXp8gs0yJg1fFhJLs5hH6neqJwhFEY7vrJEdPe87I',
'ELWWZEyBpjrfM1UU0n31KIyIXllrCoLEOI5UHD9x7WxI']
# raw binary (unqualifed) digests in string escaped form
keydigs =[b'\x98\x1d\xba\xc8\xcc\xeb\xa0\x80\xa1\xfa\x8aJ5\xd9\x18\xc8\xfd4\xd2L\x1e\xbdM|Y\x02=\xe4\x96\x89\x0e6',
b';\x80\x97\xa7\xc8,\xd3"`\xd5\xf1a$\xbb9\x84~\xa7z\xa2p\x84Q\x18\xee\xfa\xc9\x11\xd3\xde\xf3\xb2',
b'-e\x99\x13 i\x8e\xb7\xcc\xd5E4\x9f}J#"\x17\x96Z\xc2\xa0\xb1\x0e#\x95\x07\x0f\xdc{[\x12']
# now combine with XOR the raw versions of all four digests, sith plus three keys. In python must first convert to integers in order to use XOR = ^
raw = sithdig ^ keydig[0] ^ keydig[1] ^ keydig[2]
# now convert raw to fully qualified with derivation code for the digest algorithm
# in this case Blake3_256
nxt = 'E' + base64(raw)
assert nxt = 'ED8YvDrXvGuaIVZ69XsBVA5YN2pNTfQOFwgeloVHeWKs'