diff options
author | Özgür Kesim <oec@codeblau.de> | 2024-04-07 18:36:13 +0200 |
---|---|---|
committer | Özgür Kesim <oec@codeblau.de> | 2024-04-07 18:36:13 +0200 |
commit | dcdc9120d0f1fab7c2b862711f67be43ab7ca4cf (patch) | |
tree | a0d91220dc34a3c67f5f45b44baa03e1b63acc40 | |
parent | 80955c88807700977674bfcdd6535d92d9e8b241 (diff) |
schnorr: introduced schnorr signature for A=G^a
-rw-r--r-- | nizk/schnorr/schnorr.go | 77 | ||||
-rw-r--r-- | nizk/schnorr/schnorr_test.go | 34 |
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 |