An implementation of zero-knowledge deterministic nonces written in Noir—used to prevent nonce-based attacks in adversarial multi-party signing environments.
In Schnorr (and other Schnorr-like signature schemes like EdDSA), each signature requires a unique and unpredictable nonce
This method of deterministic nonce generation ensures that each nonce:
- Derives unpredictability from the private key and message via a cryptographic hash function
- Is consistent for any given message each time
- Is unique to each message and never reused for different messages
This approach allows us to be confident that our signature's security is at least as strong as the secrecy of our private key. However, in aggregated Schnorr signatures, deterministic nonces can introduce new challenges.
One of the best features of Schnorr signatures is their ability to be aggregated. A simplified understanding is:
-
Public Keys:
$P_{\text{agg}} = \sum_{i} P_i$ -
Nonce Points:
$R_{\text{agg}} = \sum_{i} R_i$ -
Signature Scalars:
$S_{\text{agg}} = \sum_{i} S_i$
However, an issue arises when aggregating signatures. Each signature
$e = H(R_{\text{agg}}, P_{\text{agg}}, m)$ $S_i = k_i + e \cdot x_i \mod n$ $R_i = k_i G$
Because the challenge
This requirement introduces a vulnerability similar to that in single-signer Schnorr. If just one party uses a weak or predictable nonce, the security of the entire signature scheme could be compromised. This leads to a conundrum:
- If nonces are purely random, signers could be manipulated into signing the same message with different nonces.
- We have no way of proving that a signer derived their nonce securely and deterministically.
The solution is to utilize a zero-knowledge proof system. By doing so, signing parties can prove that their nonce was derived deterministically from their private key and the message hash, without revealing any secret information. This approach ensures that all parties are using nonces securely, mitigating the risks associated with weak or malicious nonce generation.
The circuit takes in three inputs:
-
$p$ : (private) private key scalar -
$H(m)$ : hash of the message to sign -
$A = P + R$ : the aggregated point of the public key and nonce point
By aggregating the nonce point
This allows us to perform a single scalar multiplication inside our circuit instead of two, optimizing efficiency. When the signer eventually signs, their public key
The circuit performs the following steps:
-
Nonce Derivation: Compute
$k = H(p, H(m))$ , deriving the nonce deterministically from the private key$p$ and the message hash$H(m)$ . -
Aggregate Scalar Calculation: Compute
$a = p + k \mod n$ , combining the private key and nonce scalar modulo the curve order$n$ . -
Aggregate Point Computation: Calculate
$A' = aG$ , where$G$ is the generator point of the curve. -
Verification: Verify that
$A' = A$ , confirming that the computed point matches the provided aggregate point.
By implementing this zero-knowledge proof, we can be highly confident that all parties in an adversarial environment are generating their nonces securely and deterministically. This not only prevents nonce reuse and related attacks but also ensures that the entire signature scheme remains robust against malleability and key extraction attacks. The proof establishes that each signer adheres to the protocol without compromising their private keys, thus maintaining the cryptographic soundness of the aggregate signature.