aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nizk/schnorr/schnorr.go77
-rw-r--r--nizk/schnorr/schnorr_test.go34
2 files changed, 111 insertions, 0 deletions
diff --git a/nizk/schnorr/schnorr.go b/nizk/schnorr/schnorr.go
new file mode 100644
index 0000000..258473c
--- /dev/null
+++ b/nizk/schnorr/schnorr.go
@@ -0,0 +1,77 @@
+// 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 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)
+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 *Point) (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 *Point) 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)
+} \ No newline at end of file
diff --git a/nizk/schnorr/schnorr_test.go b/nizk/schnorr/schnorr_test.go
new file mode 100644
index 0000000..ca541de
--- /dev/null
+++ b/nizk/schnorr/schnorr_test.go
@@ -0,0 +1,34 @@
+package schnorr
+
+import (
+ "testing"
+
+ . "kesim.org/seal/nizk"
+)
+
+func TestSchnorr(t *testing.T) {
+ a, e := Curve.ScalarFromReader(nil)
+ if e != nil {
+ t.Fatal(e)
+ }
+ A := G.Exp(a)
+
+ id, e := Curve.ScalarFromReader(nil)
+ if e != nil {
+ t.Fatal(e)
+ }
+ ID := G.Exp(id)
+
+ s := (*Statement)(a)
+ c := (*Commitment)(A)
+
+ pr := s.Proof(ID)
+
+ if !c.Verify(pr, ID) {
+ t.Fatalf("Verification failed!")
+ }
+
+ if c.Verify(pr, ID.Exp(a)) {
+ t.Fatal("Verification didn't fail!")
+ }
+} \ No newline at end of file