diff options
Diffstat (limited to 'schnorr/schnorr.go')
-rw-r--r-- | schnorr/schnorr.go | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/schnorr/schnorr.go b/schnorr/schnorr.go new file mode 100644 index 0000000..ad42770 --- /dev/null +++ b/schnorr/schnorr.go @@ -0,0 +1,77 @@ +// Proof of knowledge of a for given A = G^a + +package schnorr + +import ( + . "kesim.org/seal/common" +) + +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) +} |