From 4adec77feea7e9ec45ca43084383d85de450518b Mon Sep 17 00:00:00 2001 From: Özgür Kesim Date: Mon, 11 Nov 2024 21:28:12 +0100 Subject: refactoring in progress --- auction.go | 7 +- common/common.go | 36 ++++++++++ dashboard/dashboard.go | 6 +- nizk/commit.go | 120 ++++++++++++++++++++++++++++++++ nizk/commit/commit.go | 121 -------------------------------- nizk/commit/commit_test.go | 48 ------------- nizk/commit_test.go | 48 +++++++++++++ nizk/nizk.go | 36 ---------- nizk/schnorr/schnorr.go | 4 +- nizk/schnorr/schnorr_test.go | 4 +- nizk/stage1.go | 159 ++++++++++++++++++++++++++++++++++++++++++ nizk/stage1/stage1.go | 162 ------------------------------------------- nizk/stage1/stage1_test.go | 48 ------------- nizk/stage1_test.go | 48 +++++++++++++ nizk/stage2/stage2.go | 2 +- nizk/stage2/stage2_test.go | 2 +- 16 files changed, 423 insertions(+), 428 deletions(-) create mode 100644 common/common.go create mode 100644 nizk/commit.go delete mode 100644 nizk/commit/commit.go delete mode 100644 nizk/commit/commit_test.go create mode 100644 nizk/commit_test.go delete mode 100644 nizk/nizk.go create mode 100644 nizk/stage1.go delete mode 100644 nizk/stage1/stage1.go delete mode 100644 nizk/stage1/stage1_test.go create mode 100644 nizk/stage1_test.go diff --git a/auction.go b/auction.go index 053acdd..cf46acc 100644 --- a/auction.go +++ b/auction.go @@ -11,8 +11,7 @@ import ( "log/slog" "time" - "kesim.org/seal/nizk/commit" - "kesim.org/seal/nizk/stage1" + "kesim.org/seal/nizk" ) type Type int @@ -112,13 +111,13 @@ type auction struct { observer Observer // The commitments we received from the bidders. - bidders map[string][]*commit.Commitment + bidders map[string][]*nizk.Commitment // sorted list of the bidders. bidder_ids []string // Stage 1 data per round - stage1 []*stage1.Statement + stage1 []*nizk.Stage1 log *slog.Logger } diff --git a/common/common.go b/common/common.go new file mode 100644 index 0000000..d72daaf --- /dev/null +++ b/common/common.go @@ -0,0 +1,36 @@ +package common + +import ( + "crypto/sha512" + + "kesim.org/seal/curve" +) + +// Common functions for the various proofs + +type Scalar = curve.Curve25519Scalar +type Point = curve.Curve25519Point + +var Curve = curve.Curve25519 +var G = Curve.Generator() +var One = Curve.ScalarOne() + +type Bytes interface { + Bytes() []byte +} + +type Bites []byte + +func (b Bites) Bytes() []byte { return b } + +func Challenge(bs ...Bytes) *Scalar { + h512 := sha512.New() + for _, p := range bs { + h512.Write(p.Bytes()) + } + ch, e := Curve.ScalarFromBytes(h512.Sum(nil)) + if e != nil { + panic(e) + } + return ch +} diff --git a/dashboard/dashboard.go b/dashboard/dashboard.go index 6f384f9..b26277d 100644 --- a/dashboard/dashboard.go +++ b/dashboard/dashboard.go @@ -7,7 +7,7 @@ import ( "encoding/json" "kesim.org/seal" - "kesim.org/seal/nizk/commit" + "kesim.org/seal/nizk" ) type Dashboard interface { @@ -27,7 +27,7 @@ type SignedMessage struct { } type SignedCommitment struct { - *commit.Commitment + *nizk.Commitment Signature []byte } @@ -131,4 +131,4 @@ func (s *SignedCommitment) Verify(pubkey ed25519.PublicKey) bool { func Pub2String(pubkey ed25519.PublicKey) string { return base32.StdEncoding.EncodeToString(pubkey) -} \ No newline at end of file +} diff --git a/nizk/commit.go b/nizk/commit.go new file mode 100644 index 0000000..7f46d36 --- /dev/null +++ b/nizk/commit.go @@ -0,0 +1,120 @@ +package nizk + +import ( + . "kesim.org/seal/common" + "kesim.org/seal/nizk/schnorr" +) + +// This is a construction of a proof of a statement of the form +// [(C = g^(αβ)) && (A = g^α) && (Β = g^β)] +// || [(C = g^(αβ+1)) && (A = g^α) && (Β = g^β)] +// +// for given C, A and B + +type Bid struct { + bitSet bool + α *Scalar + β *Scalar +} + +type Commitment struct { + A *Point // g^α + B *Point // g^β + C *Point // g^(ab)g^(bitSet) +} + +func NewBid(bitSet bool) *Bid { + α, β := Curve.RandomScalar(), Curve.RandomScalar() + return NewBidFromScalars(bitSet, α, β) +} + +func NewBidFromScalars(bitSet bool, α, β *Scalar) *Bid { + return &Bid{ + α: α, + β: β, + bitSet: bitSet, + } +} + +func commitment(α, β *Scalar, bitSet bool) *Commitment { + var C *Point + c := α.Mul(β) + + if bitSet { + C = G.Exp(c.Add(One)) + } else { + C = G.Exp(c) + } + return &Commitment{ + C: C, + A: G.Exp(α), + B: G.Exp(β), + } +} + +type Proof struct { + Id Bytes + A *schnorr.Proof // Proof for knowledge of α in A = G^α + B *schnorr.Proof // Proof for knowledge of β in B = G^β + C struct { // Proof for knowledge of statement above + Ch [2]*Scalar + R [2]*Scalar + } +} + +func (s *Bid) proof(id Bytes, c *Commitment) *Proof { + var e [2][2]*Point + var r1, r2, w *Scalar + r1 = Curve.RandomScalar() + r2 = Curve.RandomScalar() + w = Curve.RandomScalar() + + if s.bitSet { + e[0][0] = G.Exp(r1) + e[0][1] = c.B.Exp(r1).Mul(G.Exp(w)) + e[1][0] = G.Exp(r2) + e[1][1] = c.B.Exp(r2) + } else { + e[0][0] = G.Exp(r1) + e[0][1] = c.B.Exp(r1) + e[1][0] = G.Exp(r2).Mul(c.A.Exp(w)) + e[1][1] = c.B.Exp(r2).Mul(c.C.Div(G).Exp(w)) + } + + ch := Challenge(G, c.C, c.A, c.B, e[0][0], e[0][1], e[1][0], e[1][1], id) + pr := &Proof{Id: id} + + if s.bitSet { + pr.C.Ch[0] = w + pr.C.Ch[1] = ch.Sub(w) + pr.C.R[0] = r1.Sub(s.α.Mul(pr.C.Ch[0])) + pr.C.R[1] = r2.Sub(s.α.Mul(pr.C.Ch[1])) + } else { + pr.C.Ch[0] = ch.Sub(w) + pr.C.Ch[1] = w + pr.C.R[0] = r1.Sub(s.α.Mul(pr.C.Ch[0])) + pr.C.R[1] = r2 + } + pr.A = (*schnorr.Statement)(s.α).Proof(id) + pr.B = (*schnorr.Statement)(s.β).Proof(id) + + return pr +} + +func (s *Bid) Commit(id Bytes) (*Commitment, *Proof) { + c := commitment(s.α, s.β, s.bitSet) + return c, s.proof(id, c) +} + +func (c *Commitment) Verify(p *Proof) bool { + var e [2][2]*Point + + e[0][0] = G.Exp(p.C.R[0]).Mul(c.A.Exp(p.C.Ch[0])) + e[0][1] = c.B.Exp(p.C.R[0]).Mul(c.C.Exp(p.C.Ch[0])) + e[1][0] = G.Exp(p.C.R[1]).Mul(c.A.Exp(p.C.Ch[1])) + e[1][1] = c.B.Exp(p.C.R[1]).Mul(c.C.Div(G).Exp(p.C.Ch[1])) + ch := Challenge(G, c.C, c.A, c.B, e[0][0], e[0][1], e[1][0], e[1][1], p.Id) + return p.C.Ch[0].Add(p.C.Ch[1]).Equal(ch) && + (*schnorr.Commitment)(c.A).Verify(p.A, p.Id) && + (*schnorr.Commitment)(c.B).Verify(p.B, p.Id) +} diff --git a/nizk/commit/commit.go b/nizk/commit/commit.go deleted file mode 100644 index 49690f2..0000000 --- a/nizk/commit/commit.go +++ /dev/null @@ -1,121 +0,0 @@ -package commit - -import ( - . "kesim.org/seal/nizk" - "kesim.org/seal/nizk/schnorr" -) - -// This is a construction of a proof of a statement of the form -// [(C = g^(αβ)) && (A = g^α) && (Β = g^β)] -// || [(C = g^(αβ+1)) && (A = g^α) && (Β = g^β)] -// -// for given C, A and B - -type Bid struct { - bitSet bool - α *Scalar - β *Scalar - Commitment -} - -type Commitment struct { - A *Point // g^α - B *Point // g^β - C *Point // g^(ab)g^(bitSet) -} - -func NewBid(bitSet bool) *Bid { - α, β := Curve.RandomScalar(), Curve.RandomScalar() - return NewBidFromScalars(bitSet, α, β) -} - -func NewBidFromScalars(bitSet bool, α, β *Scalar) *Bid { - return &Bid{ - α: α, - β: β, - bitSet: bitSet, - Commitment: commitment(α, β, bitSet), - } -} - -func commitment(α, β *Scalar, bitSet bool) Commitment { - var C *Point - c := α.Mul(β) - - if bitSet { - C = G.Exp(c.Add(One)) - } else { - C = G.Exp(c) - } - return Commitment{ - C: C, - A: G.Exp(α), - B: G.Exp(β), - } -} - -func (s *Bid) Commit(id Bytes) (*Commitment, *Proof) { - return &s.Commitment, s.Proof(id) -} - -type Proof struct { - Id Bytes - A *schnorr.Proof // Proof for knowledge of α in A = G^α - B *schnorr.Proof // Proof for knowledge of β in B = G^β - C struct { // Proof for knowledge of statement above - Ch [2]*Scalar - R [2]*Scalar - } -} - -func (s *Bid) Proof(id Bytes) *Proof { - var e [2][2]*Point - var r1, r2, w *Scalar - r1 = Curve.RandomScalar() - r2 = Curve.RandomScalar() - w = Curve.RandomScalar() - - if s.bitSet { - e[0][0] = G.Exp(r1) - e[0][1] = s.B.Exp(r1).Mul(G.Exp(w)) - e[1][0] = G.Exp(r2) - e[1][1] = s.B.Exp(r2) - } else { - e[0][0] = G.Exp(r1) - e[0][1] = s.B.Exp(r1) - e[1][0] = G.Exp(r2).Mul(s.A.Exp(w)) - e[1][1] = s.B.Exp(r2).Mul(s.C.Div(G).Exp(w)) - } - - ch := Challenge(G, s.C, s.A, s.B, e[0][0], e[0][1], e[1][0], e[1][1], id) - pr := &Proof{Id: id} - - if s.bitSet { - pr.C.Ch[0] = w - pr.C.Ch[1] = ch.Sub(w) - pr.C.R[0] = r1.Sub(s.α.Mul(pr.C.Ch[0])) - pr.C.R[1] = r2.Sub(s.α.Mul(pr.C.Ch[1])) - } else { - pr.C.Ch[0] = ch.Sub(w) - pr.C.Ch[1] = w - pr.C.R[0] = r1.Sub(s.α.Mul(pr.C.Ch[0])) - pr.C.R[1] = r2 - } - pr.A = (*schnorr.Statement)(s.α).Proof(id) - pr.B = (*schnorr.Statement)(s.β).Proof(id) - - return pr -} - -func (c *Commitment) Verify(p *Proof) bool { - var e [2][2]*Point - - e[0][0] = G.Exp(p.C.R[0]).Mul(c.A.Exp(p.C.Ch[0])) - e[0][1] = c.B.Exp(p.C.R[0]).Mul(c.C.Exp(p.C.Ch[0])) - e[1][0] = G.Exp(p.C.R[1]).Mul(c.A.Exp(p.C.Ch[1])) - e[1][1] = c.B.Exp(p.C.R[1]).Mul(c.C.Div(G).Exp(p.C.Ch[1])) - ch := Challenge(G, c.C, c.A, c.B, e[0][0], e[0][1], e[1][0], e[1][1], p.Id) - return p.C.Ch[0].Add(p.C.Ch[1]).Equal(ch) && - (*schnorr.Commitment)(c.A).Verify(p.A, p.Id) && - (*schnorr.Commitment)(c.B).Verify(p.B, p.Id) -} diff --git a/nizk/commit/commit_test.go b/nizk/commit/commit_test.go deleted file mode 100644 index 111ab68..0000000 --- a/nizk/commit/commit_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package commit - -import ( - "testing" - - . "kesim.org/seal/nizk" -) - -func TestStatement(t *testing.T) { - id := Curve.RandomScalar() - Id := G.Exp(id) - - st1, st2 := NewBid(true), NewBid(false) - c1, p1 := st1.Commit(Id) - c2, p2 := st2.Commit(Id) - if !c1.Verify(p1) { - t.Fatal("Could not verify st1 with c1, plus=true case") - } - if !c2.Verify(p2) { - t.Fatal("Could not verify st2 with c2, plus=false case") - } - - // Use the wrong proof - if c2.Verify(p1) { - t.Fatal("Verify with wrong proof should have failed!") - } -} - -func TestStatementFromScalar(t *testing.T) { - var α, β, id = Curve.RandomScalar(), Curve.RandomScalar(), Curve.RandomScalar() - - Id := G.Exp(id) - - st1, st2 := NewBidFromScalars(true, α, β), NewBidFromScalars(false, α, β) - c1, p1 := st1.Commit(Id) - c2, p2 := st2.Commit(Id) - if !c1.Verify(p1) { - t.Fatal("Could not verify st1 with c1, plus=true case") - } - if !c2.Verify(p2) { - t.Fatal("Could not verify st2 with c2, plus=false case") - } - - // Use the wrong proof - if c2.Verify(p1) { - t.Fatal("Verify with wrong proof should have failed!") - } -} diff --git a/nizk/commit_test.go b/nizk/commit_test.go new file mode 100644 index 0000000..32d337b --- /dev/null +++ b/nizk/commit_test.go @@ -0,0 +1,48 @@ +package nizk + +import ( + "testing" + + . "kesim.org/seal/common" +) + +func TestStatement(t *testing.T) { + id := Curve.RandomScalar() + Id := G.Exp(id) + + st1, st2 := NewBid(true), NewBid(false) + c1, p1 := st1.Commit(Id) + c2, p2 := st2.Commit(Id) + if !c1.Verify(p1) { + t.Fatal("Could not verify st1 with c1, plus=true case") + } + if !c2.Verify(p2) { + t.Fatal("Could not verify st2 with c2, plus=false case") + } + + // Use the wrong proof + if c2.Verify(p1) { + t.Fatal("Verify with wrong proof should have failed!") + } +} + +func TestStatementFromScalar(t *testing.T) { + var α, β, id = Curve.RandomScalar(), Curve.RandomScalar(), Curve.RandomScalar() + + Id := G.Exp(id) + + st1, st2 := NewBidFromScalars(true, α, β), NewBidFromScalars(false, α, β) + c1, p1 := st1.Commit(Id) + c2, p2 := st2.Commit(Id) + if !c1.Verify(p1) { + t.Fatal("Could not verify st1 with c1, plus=true case") + } + if !c2.Verify(p2) { + t.Fatal("Could not verify st2 with c2, plus=false case") + } + + // Use the wrong proof + if c2.Verify(p1) { + t.Fatal("Verify with wrong proof should have failed!") + } +} diff --git a/nizk/nizk.go b/nizk/nizk.go deleted file mode 100644 index a8bdaae..0000000 --- a/nizk/nizk.go +++ /dev/null @@ -1,36 +0,0 @@ -package nizk - -import ( - "crypto/sha512" - - "kesim.org/seal/curve" -) - -// Common functions for the various proofs - -type Scalar = curve.Curve25519Scalar -type Point = curve.Curve25519Point - -var Curve = curve.Curve25519 -var G = Curve.Generator() -var One = Curve.ScalarOne() - -type Bytes interface { - Bytes() []byte -} - -type Bites []byte - -func (b Bites) Bytes() []byte { return b } - -func Challenge(bs ...Bytes) *Scalar { - h512 := sha512.New() - for _, p := range bs { - h512.Write(p.Bytes()) - } - ch, e := Curve.ScalarFromBytes(h512.Sum(nil)) - if e != nil { - panic(e) - } - return ch -} diff --git a/nizk/schnorr/schnorr.go b/nizk/schnorr/schnorr.go index 124155a..ad42770 100644 --- a/nizk/schnorr/schnorr.go +++ b/nizk/schnorr/schnorr.go @@ -3,7 +3,7 @@ package schnorr import ( - . "kesim.org/seal/nizk" + . "kesim.org/seal/common" ) type Statement Scalar @@ -74,4 +74,4 @@ func (c *Commitment) Verify(p *Proof, id Bytes) bool { // 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 index ca541de..2adec8e 100644 --- a/nizk/schnorr/schnorr_test.go +++ b/nizk/schnorr/schnorr_test.go @@ -3,7 +3,7 @@ package schnorr import ( "testing" - . "kesim.org/seal/nizk" + . "kesim.org/seal/common" ) func TestSchnorr(t *testing.T) { @@ -31,4 +31,4 @@ func TestSchnorr(t *testing.T) { if c.Verify(pr, ID.Exp(a)) { t.Fatal("Verification didn't fail!") } -} \ No newline at end of file +} diff --git a/nizk/stage1.go b/nizk/stage1.go new file mode 100644 index 0000000..7e28ca9 --- /dev/null +++ b/nizk/stage1.go @@ -0,0 +1,159 @@ +package nizk + +import . "kesim.org/seal/common" + +// Implements the proof and verification of statements of the following form: +// [ Z=g^(xy) && X=g^x && Y=g^y && C=g^(αβ) && A=g^α && B=g^β ] +// || [ Z=g^(xr) && X=g^x && R=g^r && C=g^(αβ+1) && A=g^α && B=g^β ] +// for given Z, X, Y, R, C, A and B + +type Stage1 struct { + x *Scalar + y *Scalar + r *Scalar + α *Scalar + β *Scalar + bitSet bool +} + +type Stage1Commitment struct { + A *Point + B *Point + C *Point + R *Point + X *Point + Y *Point + Z *Point +} + +func NewStage1(bitSet bool) *Stage1 { + var x [5]*Scalar + for i := range x { + x[i] = Curve.RandomScalar() + } + return NewStage1FromScalars(bitSet, x[0], x[1], x[2], x[3], x[4]) +} + +func NewStage1FromScalars(bitSet bool, x, y, r, α, β *Scalar) *Stage1 { + return &Stage1{ + x: x, + y: y, + r: r, + α: α, + β: β, + bitSet: bitSet, + } +} + +func (s *Stage1) commit() *Stage1Commitment { + var Z *Point + φ := s.α.Mul(s.β) + if s.bitSet { + Z = G.Exp(s.x.Mul(s.r)) + φ = φ.Add(One) + } else { + Z = G.Exp(s.x.Mul(s.y)) + } + + return &Stage1Commitment{ + Z: Z, + X: G.Exp(s.x), + Y: G.Exp(s.y), + R: G.Exp(s.r), + A: G.Exp(s.α), + B: G.Exp(s.β), + C: G.Exp(φ), + } +} + +type Stage1Proof struct { + Ch [2]*Scalar + Rho [2][2]*Scalar +} + +func (s *Stage1) proof(c *Stage1Commitment) *Stage1Proof { + var ε [2][4]*Point + var r1, r2, ρ1, ρ2, ω *Scalar + for _, s := range []**Scalar{&r1, &r2, &ρ1, &ρ2, &ω} { + *s = Curve.RandomScalar() + } + + if s.bitSet { + ε[0][0] = G.Exp(r1).Mul(c.X.Exp(ω)) + ε[0][1] = G.Exp(r2).Mul(c.A.Exp(ω)) + ε[0][2] = c.Y.Exp(r1).Mul(c.Z.Exp(ω)) + ε[0][3] = c.B.Exp(r2).Mul(c.C.Exp(ω)) + ε[1][0] = G.Exp(ρ1) + ε[1][1] = G.Exp(ρ2) + ε[1][2] = c.R.Exp(ρ1) + ε[1][3] = c.B.Exp(ρ2) + } else { + ε[0][0] = G.Exp(r1) + ε[0][1] = G.Exp(r2) + ε[0][2] = c.Y.Exp(r1) + ε[0][3] = c.B.Exp(r2) + ε[1][0] = G.Exp(ρ1).Mul(c.X.Exp(ω)) + ε[1][1] = G.Exp(ρ2).Mul(c.A.Exp(ω)) + ε[1][2] = c.R.Exp(ρ1).Mul(c.Z.Exp(ω)) + ε[1][3] = c.B.Exp(ρ2).Mul(c.C.Div(G).Exp(ω)) + } + + p := []Bytes{G, c.A, c.B, c.C, c.R, c.X, c.Y, c.Z} + for _, e := range ε[0] { + p = append(p, e) + } + for _, e := range ε[1] { + p = append(p, e) + } + + ch := Challenge(p...) + pr := &Stage1Proof{} + + if s.bitSet { + pr.Ch[0] = ω + pr.Ch[1] = ch.Sub(ω) + pr.Rho[0][0] = r1 + pr.Rho[0][1] = r2 + pr.Rho[1][0] = ρ1.Sub(s.x.Mul(pr.Ch[1])) + pr.Rho[1][1] = ρ2.Sub(s.α.Mul(pr.Ch[1])) + } else { + pr.Ch[0] = ch.Sub(ω) + pr.Ch[1] = ω + pr.Rho[0][0] = r1.Sub(s.x.Mul(pr.Ch[0])) + pr.Rho[0][1] = r2.Sub(s.α.Mul(pr.Ch[0])) + pr.Rho[1][0] = ρ1 + pr.Rho[1][1] = ρ2 + } + + return pr +} + +func (s *Stage1) Commit() (*Stage1Commitment, *Stage1Proof) { + c := s.commit() + return c, s.proof(c) +} + +func (c *Stage1Commitment) Verify(p *Stage1Proof) bool { + var ε [2][4]*Point + + ε[0][0] = G.Exp(p.Rho[0][0]).Mul(c.X.Exp(p.Ch[0])) + ε[0][1] = G.Exp(p.Rho[0][1]).Mul(c.A.Exp(p.Ch[0])) + ε[0][2] = c.Y.Exp(p.Rho[0][0]).Mul(c.Z.Exp(p.Ch[0])) + ε[0][3] = c.B.Exp(p.Rho[0][1]).Mul(c.C.Exp(p.Ch[0])) + ε[1][0] = G.Exp(p.Rho[1][0]).Mul(c.X.Exp(p.Ch[1])) + ε[1][1] = G.Exp(p.Rho[1][1]).Mul(c.A.Exp(p.Ch[1])) + ε[1][2] = c.R.Exp(p.Rho[1][0]).Mul(c.Z.Exp(p.Ch[1])) + ε[1][3] = c.B.Exp(p.Rho[1][1]).Mul(c.C.Div(G).Exp(p.Ch[1])) + + points := []Bytes{G, c.A, c.B, c.C, c.R, c.X, c.Y, c.Z} + for _, e := range ε[0] { + points = append(points, e) + } + for _, e := range ε[1] { + points = append(points, e) + } + + ch := Challenge(points...) + + return p.Ch[0].Add(p.Ch[1]).Equal(ch) +} diff --git a/nizk/stage1/stage1.go b/nizk/stage1/stage1.go deleted file mode 100644 index 5c729c8..0000000 --- a/nizk/stage1/stage1.go +++ /dev/null @@ -1,162 +0,0 @@ -package stage1 - -import ( - . "kesim.org/seal/nizk" -) - -// Implements the proof and verification of statements of the following form: -// [ Z=g^(xy) && X=g^x && Y=g^y && C=g^(αβ) && A=g^α && B=g^β ] -// || [ Z=g^(xr) && X=g^x && R=g^r && C=g^(αβ+1) && A=g^α && B=g^β ] -// for given Z, X, Y, R, C, A and B - -type Statement struct { - x *Scalar - y *Scalar - r *Scalar - α *Scalar - β *Scalar - bitSet bool - *Commitment -} - -type Commitment struct { - A *Point - B *Point - C *Point - R *Point - X *Point - Y *Point - Z *Point -} - -func NewStatement(bitSet bool) *Statement { - var x [5]*Scalar - for i := range x { - x[i] = Curve.RandomScalar() - } - return NewStatementFromScalars(bitSet, x[0], x[1], x[2], x[3], x[4]) -} - -func NewStatementFromScalars(bitSet bool, x, y, r, α, β *Scalar) *Statement { - return &Statement{ - x: x, - y: y, - r: r, - α: α, - β: β, - bitSet: bitSet, - Commitment: commitment(x, y, r, α, β, bitSet), - } -} - -func commitment(x, y, r, α, β *Scalar, bitSet bool) *Commitment { - var Z *Point - φ := α.Mul(β) - if bitSet { - Z = G.Exp(x.Mul(r)) - φ = φ.Add(One) - } else { - Z = G.Exp(x.Mul(y)) - } - - return &Commitment{ - Z: Z, - X: G.Exp(x), - Y: G.Exp(y), - R: G.Exp(r), - A: G.Exp(α), - B: G.Exp(β), - C: G.Exp(φ), - } -} - -func (s *Statement) Commit() *Commitment { - return s.Commitment -} - -type Proof struct { - Ch [2]*Scalar - Rho [2][2]*Scalar -} - -func (s *Statement) Proof() *Proof { - var ε [2][4]*Point - var r1, r2, ρ1, ρ2, ω *Scalar - for _, s := range []**Scalar{&r1, &r2, &ρ1, &ρ2, &ω} { - *s = Curve.RandomScalar() - } - - if s.bitSet { - ε[0][0] = G.Exp(r1).Mul(s.X.Exp(ω)) - ε[0][1] = G.Exp(r2).Mul(s.A.Exp(ω)) - ε[0][2] = s.Y.Exp(r1).Mul(s.Z.Exp(ω)) - ε[0][3] = s.B.Exp(r2).Mul(s.C.Exp(ω)) - ε[1][0] = G.Exp(ρ1) - ε[1][1] = G.Exp(ρ2) - ε[1][2] = s.R.Exp(ρ1) - ε[1][3] = s.B.Exp(ρ2) - } else { - ε[0][0] = G.Exp(r1) - ε[0][1] = G.Exp(r2) - ε[0][2] = s.Y.Exp(r1) - ε[0][3] = s.B.Exp(r2) - ε[1][0] = G.Exp(ρ1).Mul(s.X.Exp(ω)) - ε[1][1] = G.Exp(ρ2).Mul(s.A.Exp(ω)) - ε[1][2] = s.R.Exp(ρ1).Mul(s.Z.Exp(ω)) - ε[1][3] = s.B.Exp(ρ2).Mul(s.C.Div(G).Exp(ω)) - } - - p := []Bytes{G, s.A, s.B, s.C, s.R, s.X, s.Y, s.Z} - for _, e := range ε[0] { - p = append(p, e) - } - for _, e := range ε[1] { - p = append(p, e) - } - - ch := Challenge(p...) - pr := &Proof{} - - if s.bitSet { - pr.Ch[0] = ω - pr.Ch[1] = ch.Sub(ω) - pr.Rho[0][0] = r1 - pr.Rho[0][1] = r2 - pr.Rho[1][0] = ρ1.Sub(s.x.Mul(pr.Ch[1])) - pr.Rho[1][1] = ρ2.Sub(s.α.Mul(pr.Ch[1])) - } else { - pr.Ch[0] = ch.Sub(ω) - pr.Ch[1] = ω - pr.Rho[0][0] = r1.Sub(s.x.Mul(pr.Ch[0])) - pr.Rho[0][1] = r2.Sub(s.α.Mul(pr.Ch[0])) - pr.Rho[1][0] = ρ1 - pr.Rho[1][1] = ρ2 - } - - return pr -} - -func (c *Commitment) Verify(p *Proof) bool { - var ε [2][4]*Point - - ε[0][0] = G.Exp(p.Rho[0][0]).Mul(c.X.Exp(p.Ch[0])) - ε[0][1] = G.Exp(p.Rho[0][1]).Mul(c.A.Exp(p.Ch[0])) - ε[0][2] = c.Y.Exp(p.Rho[0][0]).Mul(c.Z.Exp(p.Ch[0])) - ε[0][3] = c.B.Exp(p.Rho[0][1]).Mul(c.C.Exp(p.Ch[0])) - ε[1][0] = G.Exp(p.Rho[1][0]).Mul(c.X.Exp(p.Ch[1])) - ε[1][1] = G.Exp(p.Rho[1][1]).Mul(c.A.Exp(p.Ch[1])) - ε[1][2] = c.R.Exp(p.Rho[1][0]).Mul(c.Z.Exp(p.Ch[1])) - ε[1][3] = c.B.Exp(p.Rho[1][1]).Mul(c.C.Div(G).Exp(p.Ch[1])) - - points := []Bytes{G, c.A, c.B, c.C, c.R, c.X, c.Y, c.Z} - for _, e := range ε[0] { - points = append(points, e) - } - for _, e := range ε[1] { - points = append(points, e) - } - - ch := Challenge(points...) - - return p.Ch[0].Add(p.Ch[1]).Equal(ch) -} diff --git a/nizk/stage1/stage1_test.go b/nizk/stage1/stage1_test.go deleted file mode 100644 index df93cdb..0000000 --- a/nizk/stage1/stage1_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package stage1 - -import ( - "testing" - - . "kesim.org/seal/nizk" -) - -func TestStatement(t *testing.T) { - st1 := NewStatement(true) - st2 := NewStatement(false) - - c1, c2 := st1.Commit(), st2.Commit() - pr1, pr2 := st1.Proof(), st2.Proof() - if !c1.Verify(pr1) { - t.Fatal("Could not verify st1 with c1 and pr1, plus=true case") - } - if !c2.Verify(pr2) { - t.Fatal("Could not verify st2 with c2 and pr2, plus=false case") - } - // Wrong proof test - if c1.Verify(pr2) { - t.Fatal("Shouldn't be able to verify c1 with pr2") - } -} - -func TestStatementFromScalars(t *testing.T) { - var x, y, r, α, β *Scalar - for _, s := range []**Scalar{&x, &y, &r, &α, &β} { - *s = Curve.RandomScalar() - } - - st1 := NewStatementFromScalars(true, x, y, r, α, β) - st2 := NewStatementFromScalars(false, x, y, r, α, β) - - c1, c2 := st1.Commit(), st2.Commit() - pr1, pr2 := st1.Proof(), st2.Proof() - if !c1.Verify(pr1) { - t.Fatal("Could not verify st1 with c1 and pr1, plus=true case") - } - if !c2.Verify(pr2) { - t.Fatal("Could not verify st2 with c2 and pr2, plus=false case") - } - // Wrong proof test - if c1.Verify(pr2) { - t.Fatal("Shouldn't be able to verify c1 with pr2") - } -} diff --git a/nizk/stage1_test.go b/nizk/stage1_test.go new file mode 100644 index 0000000..c429e69 --- /dev/null +++ b/nizk/stage1_test.go @@ -0,0 +1,48 @@ +package nizk + +import ( + "testing" + + . "kesim.org/seal/common" +) + +func TestStage1(t *testing.T) { + st1 := NewStage1(true) + st2 := NewStage1(false) + + c1, pr1 := st1.Commit() + c2, pr2 := st2.Commit() + if !c1.Verify(pr1) { + t.Fatal("Could not verify st1 with c1 and pr1, plus=true case") + } + if !c2.Verify(pr2) { + t.Fatal("Could not verify st2 with c2 and pr2, plus=false case") + } + // Wrong proof test + if c1.Verify(pr2) { + t.Fatal("Shouldn't be able to verify c1 with pr2") + } +} + +func TestStage1FromScalars(t *testing.T) { + var x, y, r, α, β *Scalar + for _, s := range []**Scalar{&x, &y, &r, &α, &β} { + *s = Curve.RandomScalar() + } + + st1 := NewStage1FromScalars(true, x, y, r, α, β) + st2 := NewStage1FromScalars(false, x, y, r, α, β) + + c1, pr1 := st1.Commit() + c2, pr2 := st2.Commit() + if !c1.Verify(pr1) { + t.Fatal("Could not verify st1 with c1 and pr1, plus=true case") + } + if !c2.Verify(pr2) { + t.Fatal("Could not verify st2 with c2 and pr2, plus=false case") + } + // Wrong proof test + if c1.Verify(pr2) { + t.Fatal("Shouldn't be able to verify c1 with pr2") + } +} diff --git a/nizk/stage2/stage2.go b/nizk/stage2/stage2.go index 88bfa59..d4d2716 100644 --- a/nizk/stage2/stage2.go +++ b/nizk/stage2/stage2.go @@ -1,7 +1,7 @@ package stage2 import ( - . "kesim.org/seal/nizk" + . "kesim.org/seal/common" ) // Implements the proof and verification of a statement of the following form: diff --git a/nizk/stage2/stage2_test.go b/nizk/stage2/stage2_test.go index a33a468..fadcc45 100644 --- a/nizk/stage2/stage2_test.go +++ b/nizk/stage2/stage2_test.go @@ -3,7 +3,7 @@ package stage2 import ( "testing" - . "kesim.org/seal/nizk" + . "kesim.org/seal/common" ) func TestVerification(t *testing.T) { -- cgit v1.2.3