Documentation ¶
Overview ¶
Package schnorr provides the underlying STROBE protocol for Veil's Schnorr signatures.
Signing A Message ¶
Signing is as follows, given a message in blocks M_0…M_n, a private scalar d, and a public element Q:
INIT('veil.schnorr', level=256) SEND_CLR('', more=false) SEND_CLR(M_0, more=true) SEND_CLR(M_1, more=true) … SEND_CLR(M_n, more=true) AD(Q)
(The signer's public key is included after the message to allow veil.mres to search for a header without having to buffer the results.)
The protocol's state is then cloned, the clone is keyed with 64 bytes of random data and the signer's private key, an ephemeral scalar is derived from PRF output:
KEY(rand(64)) KEY(d) PRF(64) -> r
The clone's state is discarded, and r is returned to the parent:
R = G^r AD(R) PRF(64) -> c s = d_s*c + r
The resulting signature consists of the two scalars, c and s.
Verifying A Signature ¶
To verify, veil.schnorr is run with associated data D, message in blocks M_0…M_n, a public element Q:
INIT('veil.schnorr', level=256) RECV_CLR('', more=false) RECV_CLR(M_0, more=true) RECV_CLR(M_1, more=true) … RECV_CLR(M_n, more=true) AD(Q) R' = Q^-c + G^s AD(R') PRF(64) -> c'
Finally, the verifier compares c' == c. If the two scalars are equivalent, the signature is valid.
Security, Forgeability, and Malleability ¶
This construction is equivalent to Construction 13.12 of Modern Cryptography 3e, and is the combination of the Fiat-Shamir transform applied to the Schnorr identification scheme, and per Theorem 13.11, secure if the discrete-logarithm problem is hard relative to ristretto255.
The Schnorr signature scheme is strongly unforgeable under chosen message attack (SUF-CMA) in the random oracle model (https://www.di.ens.fr/david.pointcheval/Documents/Papers/2000_joc.pdf) and even with practical cryptographic hash functions (http://www.neven.org/papers/schnorr.pdf). As a consequence, the signatures are non-malleable.
Indistinguishability and Pseudorandomness ¶
Per Fleischhacker et al. (https://eprint.iacr.org/2011/673.pdf), this construction produces indistinguishable signatures (i.e., signatures which do not reveal anything about the signing key or signed message). When encrypted with an unrelated key (i.e., via veil.mres), the construction is isomorphic to Fleischhacker et al.'s DRPC compiler for producing pseudorandom signatures, which are indistinguishable from random.
Ephemeral Scalar Hedging ¶
In deriving the ephemeral scalar from a cloned context, veil.schnorr uses Aranha et al.'s "hedged signature" technique (https://eprint.iacr.org/2019/956.pdf) to mitigate against both catastrophic randomness failures and differential fault attacks against purely deterministic signature schemes.
Index ¶
Constants ¶
const ( // SignatureSize is the length of a signature in bytes. SignatureSize = 2 * internal.ScalarSize )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Signer ¶
Signer is an io.Writer which adds written data to a STROBE protocol for signing.
func (*Signer) Sign ¶
func (sn *Signer) Sign(d *ristretto255.Scalar, q *ristretto255.Element) ([]byte, error)
Sign uses the given key pair to construct a Schnorr signature of the previously written data.
type Verifier ¶
Verifier is an io.Writer which adds written data to a STROBE protocol for verification.
func NewVerifier ¶
NewVerifier returns a new Verifier instance.