Schnorr

Schnorr, together with ECDSA, were two new signature algorithms introduced in Plutus during Cardano's Valentine upgrade. MuSig2 is a two-round multi-signature scheme will be integrated to Hydra.

Generalised specification

This section presents the generalized signature system ECDSA and MuSig2. In the [parameter] (#parameters-of-instantiation) section, we present the specific parameters used in Cardano and MuSig2 C implementation.

A Schnorr signature consists of the following three algorithms:

  • takes as input the security parameter and returns a key-pair . First, it chooses . Finally, compute , and return .
  • takes as input a keypair and a message , and returns a signature . Let . Compute , then compute , and finally compute . The signature is .
  • takes as input a message , a verification key and a signature , and returns depending on whether the signature is valid or not. The algorithm returns if

Let be the number of signers and be the number of nonces. A two-round multi-signature scheme MuSig2 that outputs an ordinary Schnorr signature includes the following steps:

  • takes as input the security parameter and returns a key-pair . First, it chooses . Finally, compute , and return .

  • takes as input the security parameter and returns key-pairs . First, it chooses the nonces . Finally, computes the commitments , and returns the list including tuples of nonces and commitments.

  • takes the list of public keys and the signer's public key, returns the aggregate public key and . First creates . Computes for . Finally, generates the aggregate public key by and the signer keeps her own .

  • takes the list of all signers' commitment lists, returns the list of aggregate commitments. .

  • takes as input the keypair of the signer, a message , aggregate public key, the list of commitments and the list of nonces of the signer. Returns a signature . First, creates . Computes and . The single signature is calculated as .

  • takes the list of all signers' single signatures and aggregate commitment, returns the aggregate signature where .

  • takes as input a message, aggregate verification key, aggregate signature, and aggregate commitment. Computes and accepts the signature if .

Parameters of instantiation

The above is the standard definition, and in cardano we instantiate it over curve SECP256k1. Moreover, we follow BIP-0340. The following are the two specifications of the above algorithm required for compatibility. Citing literally BIP-0340:

  • We use implicit Y coordinates. We encode an elliptic curve point with 32 bytes, and we implicitly choose the Y coordinate that is even[6].
  • We use tagged hashed of SHA256 for the challenge computation. More precisely, in order to compute H(R, vk, m), one computes SHA256(SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge") || R || vk || m).

More precisely, the following is what is the specification used in the plutus built-in functions:

  • The verification key must correspond to the (x, y) coordinates of a point on the SECP256k1 curve, where x, y are unsigned integers in big-endian form.
  • The verification key must correspond to a result produced by secp256k1_xonly_pubkey_serialize. This implies all of the following:
    • The verification key is 32 bytes long.
    • The bytes of the signature correspond to the x coordinate.
  • The input to verify is the message to be checked; this can be of any length, and can contain any bytes in any position.
  • The signature must correspond to a point R on the SECP256k1 curve, and an unsigned integer s in big-endian form.
  • The signature must follow the BIP-340 standard for encoding. This implies all the following:
    • The signature is 64 bytes long.
    • The first 32 bytes are the bytes of the x coordinate of R, as a big-endian unsigned integer.
    • The last 32 bytes are the bytes of s.
        ┏━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓
        ┃ R <32 bytes> │ s <32 bytes>  ┃
        ┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛
        <--------- signature ---------->