It is not the first time digital signatures appear on this blog as we have already introduced the ECDSA signatures earlier, as well as a more general introduction to the elliptic curve cryptography, which has been provided in the Diffie-Hellman key exchange over elliptic curve tutorial.

To be honest, I was planning to write about something completely different but it was so heavily reliant on the Schnorr signature which is at the same time sufficiently different from ECDSA to deserve its blog post. The concept I was going to write about will remain a surprise at the moment. If you read it in the future you might want to check what happened next and find it immediately.

As you might have already seen in the ECDSA signatures tutorial, the digital signature permits to prove a message has been seen by a person owning a particular private-public key pair. The example we provided in that particular tutorial consisted of a mysterious message from a friend and a digital signature helped estimate which of the messages is more likely to be true.

In this tutorial we will do something similar, we will use a different kind of signature and we will produce a multi-signature, which is a signature produced by multiple individuals. The Schnorr signatures (Schnorr, n.d.) have been known before ECDSA signatures, yet they were not so widely used due to the patent which expired in the year 2008. One of the advantages is the existence of proof that breaking the Schnorr signature is equivalent to breaking the discrete logarithm problem. Another one is the linear nature of the sign making it possible to easily combine multiple signatures.

Let us break the convention and denote the private key as dd, generator point we can keep as GG. Public key is thus

P=dG\begin{aligned} P = d G \end{aligned}

and additionally, we find a random integer kk which must fit within the prime order of the group generated by GG and we produce a point on the curve as follows

R=kG\begin{aligned} R = k G \end{aligned}

then we calculate

s=kH(mP)d\begin{aligned} s = k - H(m \vert\vert P) d \end{aligned}

where mm is the signed message and \vert\vert denotes concatenation and H()H() is the hash function as those explained in our hashing functions tutorial. The signature is a tuple

<s,R>(I)\begin{aligned} \left< s, R \right> \tag{I} \end{aligned}

To verify the signature we proceed as follows. Given <s,R>\left< s, R \right> and message mm we have to check if

sG=R+H(mP)P\begin{aligned} s G = R + H(m \vert\vert P) P \end{aligned}

We will be using the minicurve library for implementing and visualizing this signature.

from minicurve import MiniCurve as mc
from minicurve.helpers import inverse

The signature method is

def sign(m, k, d, G, p):
    # calculate public key R = k*G
    R = k*G
    # calculate e = H(M || r) where || is concatenation
    e = hashtard(m, p)
    # calculate the signature
    s = np.mod(k + d*e, p)
    # signature is s, R
    return s, R

where kk is the random nonce, pp is the order of the entire finite field. We also the verification method

def verify(m, s, G, P, R, p):
    # e_v = H(M || r_v)
    e = hashtard(m, p)
    # calculate the verification
    lhs = s*G
    rhs = R+e*P
    # test if lhs = rhs
    if lhs == rhs:
        return True, lhs, rhs
    return False, lhs, rhs

The implementation is confusing, please refer to previous ECC tutorials for more details.

Now to produce multi-signature we start by combining the keys of each of the participants using curve point addition

Pc=PA+PB\begin{aligned} P_c = P_A + P_B \end{aligned}

then each of the participant is producing the signature, this should give us <sA,RA>\left< s_A, R_A \right> and <sB,RB>\left< s_B, R_B \right> for Bob. The sAs_A and sBs_B can be combined using modulo integer addition and for random points we use eliptic curve addition

sc=sA+sBmodpRc=RA+RB\begin{aligned} s_c &= s_A + s_B \mod p \\ R_c &= R_A + R_B \end{aligned}

which gives as a multi-signature <sc,Rc>\left< s_c, R_c \right>. This signature is verifiable only for the composite key PcP_c, for the individual keys of Alice and Bob it is not valid.

As usual, let us perform a little demo. Let us imagine a scenario in which a very important message needs to be signed by both Alice and Bob. The message goes as follows

I say we take off and nuke the entire site from orbit. It's the only way to be sure.

Private keys of Alice and Bob are respectively 33 and 55. Very insecure and small numbers, as they must fit in the range of prime order of group resulting from the generating point. Keys can be visualized as follows.

then their respective random nonces are 33 and 55. Along with the ready signatures and both sides of the verification equation

and we can observe that for all cases left-hand side equals the right-hand side indicating signatures validity.

If you run the source code of this example you will see the outputs confirming the validity of the result

Trying to verify the signature with just Alice's public key
failed
Trying to verify the signature with just Bob's public key
failed
Trying to verify the signature with the composite public key
valid

This was a short tutorial, but I hope it will end up useful as once we have Schnorr signatures and multi-signatures we can go into more advanced concepts, such as Pedersen commitments, confidential transactions, adaptor signatures, and much more!

If you like to know more, I based this tutorial on what the heck is Schnorr medium article and cryptography fandom Schnorr signature page.

I would like to thank John Tromp for answering my questions and providing comments regarding Schnorr’s signatures on the cryptography channel in the grincoin keybase team. I also thank vegycslol for a discussion that helped improve the quality of this tutorial and make it a lot less confusing.

If you find typos or errors in this text please do not hesitate to let me know, for which best way is to simply tweet me.

  1. Schnorr, C. P. Efficient Identification and Signatures for Smart Cards. In Advances in Cryptology — CRYPTO’ 89 Proceedings (pp. 239–252). Springer New York. 10.1007/0-387-34805-0_22

[Back to Top]