From 6c57b4cf346986fe0b5b42ceaaa5cccda597e5a0 Mon Sep 17 00:00:00 2001 From: Adam B <13562139+catenocrypt@users.noreply.github.com> Date: Sat, 15 Apr 2023 16:30:35 +0200 Subject: [PATCH] Add notes on implementation, etc --- 41.md | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/41.md b/41.md index 8686a12c..f86cd382 100644 --- a/41.md +++ b/41.md @@ -132,21 +132,12 @@ The verification process for the validity of an invalidation (`kind: 13`) event ## Additional comments + ### This is not a general "rotation" scheme for keys This scheme is intended to make it less catastrophic when a key is compromised because it was input into a computer, phone or Nostr client softwre that turns out later to have been compromised. It isn't intended to allow people to rotate their keys every month as a routine practice, nor is it supposed to let users be reckless and give their private keys to any malware or trusted third parties. A compromised key is still a bad event, just not one of awful and unrepairable consequences if this NIP is followed and relied upon. -### Notes on Implementation - -32 vs 33-byte public keys. In Nostr usually the 32-byte 'X-only' format public key is used. However, in the BIP32 scheme employed here the 33-byte 'compressed' format public key is used. The 32-byte format misses the parity. In practice this means that at verification both parity alternatives have to be checked. - -For derivation an 'off-the-shelve' BIP32-capable library implementation can be used directly, or an own implementation. The own implementation is recommended, for the reasons: - -- Due to a limitation that stems from serialization format that is not relevant here, implementations typically limit the maximum depth of a derivation path to 256, meaning that at most 253 keys could be generated in this scheme (though in practice that's probably sufficient). -- Constructing an extended public key from its parts is needed at verification, but this is not a typical operation in the BIP32 use cases, and it cannot be easily accessed, only through some workarounds. - - ### Fallback mechanism possibilities What happens if Bob is following Carol and Carol publishes an invalidation event for her key, but Bob's client doesn't see it for any reason or doesn't support the automatic refollow mechanism for the new key? Well, in this case we are at least not worse than the current state of things, but Bob has other possibilities: @@ -156,3 +147,41 @@ What happens if Bob is following Carol and Carol publishes an invalidation event - anyone with a supporting client can be 100% sure the key was really invalidated, so they can alert others about that fact without any fear of spreading wrong information; - and last but not least Bob may want to verify things manually if he sees suspicious activity from Carol's key. At least he doesn't have to ask her (and then get a response from the attacker stating that "no, it's just me, Carol!"). + + +### Why not use a fix length derivation path? + +Would it be possible to use a derivation path of fixed length, with consecutive indices to generate the keys? + +It would be possible, but rotation requires publishing the chaincode, which would allow the reconstruction of other sibling keys. Only through using an ever-growing-length derivation path it is possible to use an iterative derivation employing a hash of previous keys. + + +### Notes on Implementation + +32 vs 33-byte public keys. In Nostr usually the 32-byte 'X-only' format public key is used. However, in the BIP32 scheme employed here the 33-byte 'compressed' format public key is used. The 32-byte format misses the parity. In practice this means that at verification both parity alternatives have to be checked. + +Library vs. own implemetation. For derivation an 'off-the-shelve' BIP32-capable library implementation can be used directly, or an own implementation. The own implementation is recommended, for the following reasons: + +- Due to a limitation that stems from serialization format that is not relevant here, implementations typically limit the maximum depth of a derivation path to 256, meaning that at most 253 keys could be generated in this scheme (though in practice that's probably sufficient). +- Constructing an extended public key from its parts is needed at verification, but this is not a typical operation in the BIP32 use cases, and it cannot be easily accessed, only through some workarounds. + +By referencing BIP32, it is not the task of this spec to defined the details of the derivation. For convenience we shortly reproduce it here. +The non-hardened ESK derivation pseudo-code is: + +``` +hash64 = HMAC_SHA512(CC || PK33 || N4) +SK = SK + hash64[0..31] +CC = hash64[32..63] +``` + +where HMAC_SHA512 is the corresponding hash function, `PK33` is the 33 byte public key `||` is byte concatenation, `N4` is the 4-byte (BE) serialization of the child number `[]` denotes byte sub-array, `+` is scalar addition (using BE 32 byte numbers). +The hardened version is similar, but the hash argument is `('0' || SK32)`. + +The EPK derivation is also similarm with `+` here being point addition: + +``` +hash64 = HMAC_SHA512(CC || PK33 || N4) +PK = PK + hash64[0..31] +CC = hash64[32..63] +``` +