Using ECC for (Multi-)Signatures
Math-powered methods for proving message authenticity, sounds great, doesn't it?
04/12/2024 Β· 10 min read Β· sapling πͺ΄
I am not a cryptographer, nor a mathematician. This article is the result of my own research and understanding of the subject. If you find any mistakes, please let me know!
The vast majority of what is written here is taken from various sources, which are listed at the end of this article. I highly recommend you to read them if you want to dive deeper into the subject.
Elliptic curves may not write your emails, but they can help prove you sent them. Our goal is to output a signature for a given message , so that the recipient can verify that the sender is authentic. The senderβs keys are , with the private key, and the public one.
ECDSA Signatures
Letβs take a look at the Elliptic Curve Digital Signature Algorithm (ECDSA).
- Compute the hash where is any cryptographic hash function (e.g. SHA-256).
- Generate a random number in in the current subgroup.
- Calculate the associated random point on the curve , with a generator, with the -coordinate of this point.
- Calculate the signature , where is the modular inverse of .
By sending , you confirm you know:
- The content of the message
- The private key associated to
The verifier may follow this procedure to check if the message that he received along with is authentic:
- Compute the hash with the same cryptographic hash function defined before.
- Calculate the modular inverse of :
- Recover the random point used in the signature process:
- Check whether , if so, then the message is authentic.
To prove this works, letβs start with the definition of the signature :
Incorporate into :
Which is just our definition of when generating the signature.
Cool Kids Public Key Recovery
Letβs suppose you are talking through a Tin can telephone with your friend and every byte you send matters. You donβt want to send the public key along with the signature because thatβs just too much data. Instead, you can recover the public key from the signature and the message.
Given , there are typically two candidate points that fit. And since we know that , which we just verified works, it can be rearranged to isolate the public key :
To choose which one is the correct one, we need to verify the signature with each :
This ambiguity is often removed by adding a single bit into the signature message:
Schnorr Signatures
Schnorr signatures are a bit like ECDSA, but faster and simpler. We are going to use the same keys as before, with the private key and the public one. Weβll first see the procedure and then discuss the mathematical proof of why this works.
- Sample a random nonce
What the hell is ?
The set is a cyclic group of integers, isomorphic to the quotient group . It is basically just the set of integers modulo .
In our case, is the order (how many points are in) of the subgroup generated by . If the curveβs cofactor is 1, then is the order of the curve. If is not 1, the order is
- Multiply it by the generator:
- We can now compute the challenge
- And the signature:
The final signature is .
Once the signature has been emitted, verifying it is as easy as checking:
To know , the verifier needs to know the message , the public key . In some cases, you might not need to include the public key into the challenge and simply hash .
Why it Works
There isnβt really a proof needed for the verifying step as itβs just factoring out , but here you are:
One trickier part is to explain why we are adding a random nonce to both the signature and the challenge. This value has to be sampled randomly and must not be reused. If it is, the private key can be recovered. Letβs first take the case where no is used:
Recovering the private key is as simple as multiplying the challenge by the modular inverse of . Not good.
Now, letβs take the case where is reused, with two messages and , along with their respective signatures and :
Combining and :
You may see as an additional unknown variable that is used to prevent the linear equation system from being solved, because for messages, you have equations and unknowns, which is unsolvable in our case.
Aggregating Signatures
Schnorr signatures have the nice property that they can be aggregated, this means that a group of people can sign a message together and the signature can be verified as if it was signed by a single person. Letβs consider our signing group for Alice, Bob and Charlie respectively.
The aggregated nonce is simply the sum of all nonces:
Likewise for the public key:
Each of them computes the challenge along with the final signature with the parameters just agreed upon:
Aggregate again:
The final signature that can be sent to others is .
Because we are just adding signatures parts together, we can group the nonces and the private keys in our final signature:
In the verifying step, multiplying each side by :
But wait!
At no point in this procedure, we ever check if the nonces or the public keys provided are honest. What if Charlie provided a malicious key in the sharing step ? Because everyone doesnβt send their public key at the exact same time, Carol could wait for everyone to send theirs, and compute:
The aggregated key will look like:
Carol just wiped everyone else from the signing key, and is now in full control of the signature. How can we prevent that ?
Multi-Signatures, donβt trust, verify
The most common way to prevent this is to force everyone to provide a proof that their public key is honest. This is done by providing a Proof of Knowledge for the private key, proving that they know the private key associated to the public key they provided.
Letβs take the case of a prover Patricia and a verifier Victor. Patricia wants to prove that she knows the private key associated to the public key . The proof is done in four steps:
- Patricia samples at random and sends to Victor.
- Victor sends a challenge to Patricia.
- Patricia computes and sends it to Victor.
- Victor verifies that .
This works because:
But what if Patricia doesnβt know the associated private key but still wants to prove that her key is honest ? Remember commitment schemes ? We can use them here. In our case, every participant will commit to their public key before disclosing it. Think of it as putting your public key in a box, sealing it and waiting for everyone to do the same before opening it. Letβs get back to our group :
- Each participant hashes their public key and sends to everyone.
- Once everyone has sent their hash, they disclose their public key .
- Everyone verifies that the hash they received matches the public key.
- The signing process continues as usual.
This way, everyone can be sure that the public keys are honest and that no one is trying to pull a fast one.
Thereβs more!
Random nonces are also aggregated, and at no point we are verifying that they are authentic. The exploit method is a bit trickier, I recommend you to read this article by conduition on the subject if you want to know the details.
References / Suggested readings
Practical Cryptography for Developers - Digital Signatures
Svetlin Nakov
cryptobook.nakov.comA Dive Into the Math Behind Bitcoin Schnorr Signatures
conduition.ioWagnerβs Birthday Attack - How to Break InsecureMuSig
conduition.ioHow to Prove Schnorr Assuming Schnorr: Security of Multi- and Threshold Signatures
Elizabeth Crites, Chelsea Komlo, and Mary Maller
eprint.iacr.org