Skip to content

Latest commit

 

History

History
211 lines (156 loc) · 7.08 KB

00.md

File metadata and controls

211 lines (156 loc) · 7.08 KB

NUT-00: Notation, Utilization, and Terminology

mandatory


This document details the notation and models used throughout the specification and lays the groundwork for understanding the basic cryptography used in the Cashu protocol.

  • Sending user: Alice
  • Receiving user: Carol
  • Mint: Bob

Blind Diffie-Hellmann key exchange (BDHKE)

Variables

  • G elliptic curve generator point

Bob (mint)

  • k private key of mint (one for each amount)
  • K public key of mint
  • Q promise (blinded signature)

Alice (user)

  • x random string (secret message), corresponds to point Y on curve
  • r private key (blinding factor)
  • T blinded message
  • Z proof (unblinded signature)

hash_to_curve(x: bytes) -> curve point Y

Deterministically maps a message to a public key point on the secp256k1 curve, utilizing a domain separator to ensure uniqueness.

Y = PublicKey('02' || SHA256(msg_hash || counter)) where msg_hash is SHA256(DOMAIN_SEPARATOR || x)

  • Y derived public key
  • DOMAIN_SEPARATOR constant byte string b"Secp256k1_HashToCurve_Cashu_"
  • x message to hash
  • counter uint32 counter(byte order little endian) incremented from 0 until a point is found that lies on the curve

Protocol

  • Mint Bob publishes public key K = kG
  • Alice picks secret x and computes Y = hash_to_curve(x)
  • Alice sends to Bob: B_ = Y + rG with r being a random blinding factor (blinding)
  • Bob sends back to Alice blinded key: C_ = kB_ (these two steps are the DH key exchange) (signing)
  • Alice can calculate the unblinded key as C_ - rK = kY + krG - krG = kY = C (unblinding)
  • Alice can take the pair (x, C) as a token and can send it to Carol.
  • Carol can send (x, C) to Bob who then checks that k*hash_to_curve(x) == C (verification), and if so treats it as a valid spend of a token, adding x to the list of spent secrets.

0.1 - Models

BlindedMessage

An encrypted ("blinded") secret and an amount is sent from Alice to Bob for minting tokens or for swapping tokens. A BlindedMessage is also called an output.

{
  "amount": int,
  "id": hex_str,
  "B_": hex_str
}

amount is the value for the requested BlindSignature, id is the requested keyset ID from which we expect a signature, and B_ is the blinded secret message generated by Alice. An array [BlindedMessage] is also referred to as BlindedMessages.

BlindSignature

A BlindSignature is sent from Bob to Alice after minting tokens or after swapping tokens. A BlindSignature is also called a promise.

{
  "amount": int,
  "id": hex_str,
  "C_": hex_str
}

amount is the value of the blinded token, id is the keyset id of the mint keys that signed the token, and C_ is the blinded signature on the secret message B_ sent in the previous step.

Proof

A Proof is also called an input and is generated by Alice from a BlindSignature it received. An array [Proof] is called Proofs. Alice sends Proofs to Bob for melting tokens. Serialized Proofs can also be sent from Alice to Carol. Upon receiving the token, Carol deserializes it and requests a swap from Bob to receive new Proofs.

{
  "amount": int, 
  "id": hex_str,
  "secret": str,
  "C": hex_str,
}

amount is the amount of the Proof, secret is the secret message and is a utf-8 encoded string (the use of a 64 character hex string generated from 32 random bytes is recommended to prevent fingerprinting), C is the unblinded signature on secret (hex string), id is the keyset id of the mint public keys that signed the token (hex string).

0.2 - Protocol

Errors

In case of an error, mints respond with the HTTP status code 400 and include the following data in their response:

{
  "detail": "oops",
  "code": 1337
}

Here, detail is the error message, and code is the error code. Error codes are to be defined in the documents concerning the use of a certain API endpoint.

0.3 - Methods

Serialization of tokens

Tokens can be serialized to send them between users Alice and Carol. Serialized tokens have a Cashu token prefix, a versioning flag, and the token. Optionally, a URI prefix for making tokens clickable on the web.

We use the following format for token serialization:

cashu[version][token]

V3 tokens

Wallets serialize tokens in a base64_urlsafe format (base64 encoding with / replaced by _ and + by -).

cashu[version][base64_token_json]

cashu is the Cashu token prefix. [version] is a single base64_urlsafe character to denote the token format version (starting with A for the present token format). [base64_token_json] is the token JSON serialized in base64_urlsafe. A [base64_token_json] should be cleared of any whitespace before serializing.

Version

This token format has the [version] value A.

URI tags

To make Cashu tokens clickable on the web, we use the URI scheme cashu:. A serialized token with URI tag becomes

cashu:cashuAeyJwcm9vZn...
Token format

The deserialized base64_token_json is

{
  "token": [
    {
      "mint": str,
      "proofs": Proofs
    },
    ...
  ],
  "unit": str <optional>,
  "memo": str <optional>
}

mint is the mint URL, Proofs is an array of Proof objects. The next two elements are only for displaying the receiving user appropriate information: unit is the currency unit of the token keysets (see Keysets for supported units), and memo is an optional text memo from the sender.

Example JSON
{
  "token": [
    {
      "mint": "https://8333.space:3338",
      "proofs": [
        {
          "amount": 2,
          "id": "009a1f293253e41e",
          "secret": "407915bc212be61a77e3e6d2aeb4c727980bda51cd06a6afc29e2861768a7837",
          "C": "02bc9097997d81afb2cc7346b5e4345a9346bd2a506eb7958598a72f0cf85163ea"
        },
        {
          "amount": 8,
          "id": "009a1f293253e41e",
          "secret": "fe15109314e61d7756b0f8ee0f23a624acaa3f4e042f61433c728c7057b931be",
          "C": "029e8e5050b890a7d6c0968db16bc1d5d5fa040ea1de284f6ec69d61299f671059"
        }
      ]
    }
  ],
  "unit": "sat",
  "memo": "Thank you."
}

When serialized, this becomes:

cashuAeyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vODMzMy5zcGFjZTozMzM4IiwicHJvb2ZzIjpbeyJhbW91bnQiOjIsImlkIjoiMDA5YTFmMjkzMjUzZTQxZSIsInNlY3JldCI6IjQwNzkxNWJjMjEyYmU2MWE3N2UzZTZkMmFlYjRjNzI3OTgwYmRhNTFjZDA2YTZhZmMyOWUyODYxNzY4YTc4MzciLCJDIjoiMDJiYzkwOTc5OTdkODFhZmIyY2M3MzQ2YjVlNDM0NWE5MzQ2YmQyYTUwNmViNzk1ODU5OGE3MmYwY2Y4NTE2M2VhIn0seyJhbW91bnQiOjgsImlkIjoiMDA5YTFmMjkzMjUzZTQxZSIsInNlY3JldCI6ImZlMTUxMDkzMTRlNjFkNzc1NmIwZjhlZTBmMjNhNjI0YWNhYTNmNGUwNDJmNjE0MzNjNzI4YzcwNTdiOTMxYmUiLCJDIjoiMDI5ZThlNTA1MGI4OTBhN2Q2YzA5NjhkYjE2YmMxZDVkNWZhMDQwZWExZGUyODRmNmVjNjlkNjEyOTlmNjcxMDU5In1dfV0sInVuaXQiOiJzYXQiLCJtZW1vIjoiVGhhbmsgeW91LiJ9