3.4 KiB
NUT-2 - Keysets and keyset ID
A keyset is a set of public keys that the mint Bob generates and shares with its users. It refers to the set of public keys that each correspond to the amount values that the mint supports (e.g. 1, 2, 4, 8, ...) respectively.
Requesting mint keyset IDs
A mint can have multiple keysets at the same time but MUST have only one active keyset (see #1 [TODO: Link #1]). A wallet can ask the mint for all active keyset IDs via the GET /keysets endpoint. A wallet CAN request the list of active keyset IDs from the mint upon startup and, if it does so, MUST choose only tokens from its database that have a keyset ID supported by the mint to interact with it.
This is useful in the case a wallet interacts with multiple mints. That way, a wallet always knows which tokens it can use with the mint it is currently interacting with.
Example
Request of Alice:
GET https://mint.host:3338/keysets
With curl:
curl -X GET https://mint.host:3338/keysets
Response of Bob:
{
"keysets": [
"DSAl9nvvyfva",
...
]
}
2.1 - Generating a keyset
A keyset is generated by the mint by a single seed s from which the private keys k_i are derived, with i being the index of the amount value. The derivation for the elements k_i goes like this:
for i in range(MAX_ORDER):
k_i = HASH_SHA256(s + D + i)[:32]
Here, MAX_ORDER refers to the order of the maximum token value that the mint supports, i.e., 2^MAX_ORDER. Typically, MAX_ORDER = 64. D refers to a derivation path that is chosen by the mint. The derivation path can be used to rotate keys over time or to service multiple parallel mints with a single instance. i is the string representation of the index of the amount value, i.e., 0, 1, and so on.
2.2 - Keyset ID
A keyset ID is an identifier for a specific keyset. It can be derived by anyone who knows the set of public keys of a mint. The keyset ID CAN be stored in a Cashu token [TODO: Link to definition of token] such that the token can be used to identify which mint or keyset it was generated from.
2.2.1 - Storing the keyset ID in a token
A wallet can use the keyset ID in a token to recognize a mint it was issued by. For example, a wallet might store the MINT_URL together with the keyset_id in its database the first time it receives a keyset from that mint. That way, a wallet can know which mint to contact when it receives a token with a keyset_id of a mint that it has interacted with before.
[TODO: V2 tokens include the MINT_URL to enable the first contact when a wallet recieves a token from a mint it has never met before.]
2.2.2 - Deriving the keyset ID
The mint and the wallets of its users can derive a keyset ID from the keyset of the mint. To derive the keyset ID of a keyset, execute the following steps:
1 - sort keyset by amount
2 - concatenate all (sorted) public keys to one string
3 - HASH_SHA256 the concatenated public keys
4 - take the first 12 characters of the hash
An example implementation in Python:
def derive_keyset_id(keys: Dict[int, PublicKey]):
"""Deterministic derivation keyset_id from set of public keys."""
sorted_keys = dict(sorted(keys.items()))
pubkeys_concat = "".join([p.serialize().hex() for _, p in sorted_keys.items()])
return base64.b64encode(
hashlib.sha256((pubkeys_concat).encode("utf-8")).digest()
).decode()[:12]