// Proof of knowledge of a for given A = G^a package schnorr import ( . "kesim.org/seal/nizk" ) type Statement Scalar type Commitment Point // A Schnorr signature to prove knowledge of v for given g^v. // Choosing a scalar v randomly, the signature consists of (V, r) with // // V := g^v, with randomly chosen v // r := (v - x*h), with h := H(g, g^v, g^x, i), where i is given by the context. // // Verification of the signature is by comparing V =?= g^r * g^(x*h) type Proof struct { V *Point `json:"V"` R *Scalar `json:"r"` } // Generates a commitment // Generates the proof, aka Schnorr signature, for given priv and i. // Choosing a scalar v randomly, the signature consists of (V, r) with // // V := g^v, with randomly chosen v // r := (v - x*h), with h := H(g, g^v, g^x, i), where i is given by the context. // // Verification of the signature is by comparing V =?= g^r * g^(x*h) func (s *Statement) Proof(id Bytes) (pr *Proof) { x := (*Scalar)(s) // choose random v v := Curve.RandomScalar() pr = &Proof{} // calculate g^v pr.V = Curve.Exp(v) // calculate g^x gx := G.Exp(x) // calculate h := H(g, g^v, g^x, i) h := Challenge(pr.V, gx, id) // Calculate r := v - x*h xh := x.Mul(h) r := v.Sub(xh) pr.R = r return pr } // Verifies that g^v == g^r*g^(x*h) func (c *Commitment) Verify(p *Proof, id Bytes) bool { Gx := (*Point)(c) // Calculate h = H(g, g^v, g^x, id) h := Challenge(p.V, Gx, id) // Calculate g^(x*h) = (g^x)^h gxh := Gx.Exp(h) // Calculate g^r gr := G.Exp(p.R) // Calculate g^r*g^(x*h) grgxh := gr.Mul(gxh) // Return true if g^v == g^r*g^(x*h) return p.V.Equal(grgxh) }