I’m wondering if it’s possible to generate deterministic keypair using the Nitrokey by using a seed and some metadata (i.e BIP32). I need to be able to generate a lot of keys but must be able to retrieve any of these key at any time.
Maybe an approach could be to inject a secret key inside the smart card as an object and use it internally in the key generation function.
Is this approach feasable ?
Do I need to update the firmware for such process ?
I am not sure, what exactly you want to do, but generally the following is granted:
- keys generated on Nitrokey can not be read out, copied, backuped, guessed
- keys can be generated outside the Nitrokey and then copied to the Nitrokey. In this case you have a backup and a possibility to “loose” the keys to bad persons.
I know that the key cannot be extract, read out externally, I just would like to implement a deterministic key generation based on master seed inside the HSM to be able to provide public key and signature based on a index.
Example: Generate the n-th public key, or Sign with the n-th private key, but without store all the keys, as the number may increase a lot.
If this concerns Nitrokey HSM, please take a look at Nitrokey HSM2 Firmware update and customization for own solution. Please let me know if that would help.
Edit: interesting idea to implement on the Nitrokey Start as well.
Yes thanks ! I was thinking about a firmware customization or update.
Do you know how to perform such update ?
Please take a look at my reply in the linked post regarding the update process: Nitrokey HSM2 Firmware update and customization for own solution
The firmware customization would require contact with the smart card vendor: Nitrokey HSM2 Firmware update and customization for own solution
The SmartCard-HSM already supports a scheme to derive EC keys from a master key. The scheme was developed based on a customer request to implement a crypto wallet.
The scheme is described in chapter 2.19 of the user manual:
In order to support an unlimited number of subkeys from a randomly chosen EC private
key, the SmartCard-HSM implements the scalar addition of the private key value with an
externally provided offset. This scheme is loosely based on BIP32 to allow building
hierarchical wallets for crypto currencies.
In the given ECC equation Q = d * G, d is the private key, G the generator point of the
curve and Q the public point. For a transformation d’ = (d + i) mod n, with i the scalar to
add and n the order of the curve, the public key value can be computed as Q’ = (d + i) *
G, which is equal to Q’ = d * G + i * G and Q’ = Q + i * G.
As such an application can easily determine Q’ from Q and use the SmartCard-HSM to
derive a subkey given the scalar offset.
EC key derivation is implemented using the DERIVE KEY (2.19) command.
An example is provided in the deriveECKey.js script that is part of the SmartCard-HSM SDK. It can be downloaded as part of the Starterkit and is contained in the sc-hsm-workspace.zip. Just unpack the zip, install the Smart Card Shell and select the unzipped folder as workspace. The script is contained in the sc-hsm-sdk-scripts/examples folder.
Note, though, that scalar addition is equivalent to the non-hardened child key derivations of BIP-32. That means any private key can be calculated from any other private key with the knowledge of
i, which I would not classify as secret information. Thus the hierarchy aspect of the scheme is more related to privacy (a valid concern for crypto wallets) than to separate owners of private keys from each other.
I’m interested in the second use case, though: Deriving a child private key from a parent private key, such that the parent private key cannot be calculated from the child private key (one-wayness of the derivation). I don’t suppose there has been any development in this regards since May 2020?
My current fallback idea is to derive a hierarchy of symmetric keys from a root symmetric key and deterministically derive the asymmetric keys from the symmetric keys. E.g. given a parent symmetric key
s_p, I would generate the child symmetric key
s_c from static and public information
s_c = HMAC(s_p, "symmetric next level" || i) and the child asymmetric private key
a_c (the private multiple of the generator) as
a_c = HMAC(s_c, "asymmetric from symmetric") mod n, where
n is the order of the curve.
a_p are stored on a Nitrokey with a given cryptographic domain (i.e. shared DKEK), then
s_c and thus
a_c can leave the Nitrokey (and its domain) and be loaded on a new Nitrokey with a different cryptographic domain (i.e. different shared DKEK).
Why I’m interested in all that: I’m designing a private and local PKI and want to give away some responsibilities to outside parties. Those can get their intermediate CA private keys on pre-initialized HSMs only, so they don’t have the ability to store the private key insecurely. For various reasons, the PKI root owners might want to take back the responsibilities of the outside parties. In that case it is often useful to have access to the private key of the previously outsourced intermediate CA, e.g. for certificate revocations for the certificate issued by the intermediate CA. All of this is possible without deterministic key derivations, but the process that is required to guarantee secrecy and availability in small scale PKI is greatly simplified with deterministic key derivations. Think 3 slips of paper in three different safes, which would be sufficient to recover from any hardware failure.
But you neither know the parent key’s value nor the child key value, as both are stored in the HSM. You only know the scalar i as derivation parameter.
The scalar addition is of course done in the HSM, so the private key value or intermediate results are never disclosed.