-
Notifications
You must be signed in to change notification settings - Fork 0
feat(specs): add NXP-2 - Derivation Path Standards #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Define comprehensive key derivation standards for Nexum: - BIP-44 paths for account signing keys - EIP-1581 paths for encryption and non-wallet keys - Delegation key derivation from account addresses - Domain-separated key derivation patterns Closes nxm-rs/nexum#86 Related to nxm-rs/pm#3 (EPIC 0.0)
| @dataclass | ||
| class ExtendedKey: | ||
| private_key: int | ||
| chain_code: bytes | ||
|
|
||
| def try_derive(parent: ExtendedKey, index: int) -> ExtendedKey | None: | ||
| """Attempt to derive a child key. Returns None if derivation is invalid.""" | ||
| data = serialize(parent, index) | ||
| i = hmac.new(parent.chain_code, data, hashlib.sha512).digest() | ||
| i_l, i_r = i[:32], i[32:] | ||
|
|
||
| # Check validity per BIP-32 | ||
| parsed_key = int.from_bytes(i_l, byteorder='big') | ||
| if parsed_key >= SECP256K1_ORDER: | ||
| return None # Invalid: I_L >= curve order | ||
|
|
||
| child_key = (parsed_key + parent.private_key) % SECP256K1_ORDER | ||
| if child_key == 0: | ||
| return None # Invalid: resulting key is zero | ||
|
|
||
| return ExtendedKey(private_key=child_key, chain_code=i_r) | ||
|
|
||
| def derive_with_retry(parent: ExtendedKey, start_index: int) -> tuple[ExtendedKey, int]: | ||
| """Derive child key, incrementing index on failure until valid.""" | ||
| index = start_index | ||
|
|
||
| while True: | ||
| result = try_derive(parent, index) | ||
| if result is not None: | ||
| return (result, index) | ||
| index += 1 # Increment and retry | ||
|
|
||
| # Safety check (should never be reached in practice) | ||
| if index > 0xFFFFFFFF: | ||
| raise ValueError("Exhausted index space") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we dont need to show bip32 implementation in this nxp
| ``` | ||
|
|
||
| Where: | ||
| - `44'` — BIP-44 purpose (hardened) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think its more interesting to set this 44 to a DELEGATING_PURPOSE instead that is defined in some other nxp for common delegation purposes.
| |------|------------|-------| | ||
| | `m/44'/60'/*/0/*` | No | Standard accounts stay on-card | | ||
| | `m/44'/60'/*/1/*` | No | Delegation keys stay on-card | | ||
| | `m/43'/60'/1581'/*` | Yes | EIP-1581 encryption keys only | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so maybe you want to explicitly DISALLOW identity index to be 1581 in nxp-1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not an issue as 1581 for an identity index is fine as the identity index will be under the 44' purpose code, whereas for EIP-1581 derived keys, these fall under the 43' purpose code.
Summary
Context
NXP-2 builds on NXP-1's identity model to define the exact derivation paths used for all key types. It distinguishes between signing keys (which remain on secure elements) and encryption/delegation keys (which must be exported for software operations).
Closes nxm-rs/nexum#86
Related to nxm-rs/pm#3 (EPIC 0.0)
Test plan