diff options
author | Özgür Kesim <oec@codeblau.de> | 2024-11-21 17:13:47 +0100 |
---|---|---|
committer | Özgür Kesim <oec@codeblau.de> | 2024-11-21 17:13:47 +0100 |
commit | 0ada8c47427bfe604024d383ed7a250b04c82fee (patch) | |
tree | 4bc5e6432512a8060308413d303b675b0658bd1b /stage1.go | |
parent | 32cee46e39527a09504615b822cc61969c46184d (diff) |
Diffstat (limited to 'stage1.go')
-rw-r--r-- | stage1.go | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/stage1.go b/stage1.go new file mode 100644 index 0000000..d1ac814 --- /dev/null +++ b/stage1.go @@ -0,0 +1,196 @@ +package seal + +import ( + . "kesim.org/seal/common" +) + +type Stage struct { + x *Scalar + r *Scalar + + *StageCommitment + *StageReveal + Sent bool +} + +type StageCommitment struct { + R *Point + X *Point +} + +type StageReveal struct { + Y *Point + Z *Point +} + +// Represents the proof 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 Stage1Proof struct { + Ch [2]*Scalar + Rho [2][2]*Scalar +} + +func (b *Bit) stage(x, r *Scalar) { + b.Stage = &Stage{ + x: x, + r: r, + } +} + +func (s *Stage) commit() *StageCommitment { + if s.StageCommitment != nil { + return s.StageCommitment + } + + s.StageCommitment = &StageCommitment{ + X: G.Exp(s.x), + R: G.Exp(s.r), + } + return s.StageCommitment +} + +func (b *Bit) StageCommit() (s *StageCommitment) { + if b.Stage != nil { + return b.Stage.StageCommitment + } + x := Curve.RandomScalar() + r := Curve.RandomScalar() + return b.StageFromScalars(x, r) +} + +func (b *Bit) StageFromScalars(x, r *Scalar) (c *StageCommitment) { + b.stage(x, r) + return b.Stage.commit() +} + +func (b *Bit) reveal(prev_true bool, Xs ...*Point) (r *StageReveal) { + s := b.Stage + + // Calculate Y based on the Xs and our own X_i + // as Π_(i<k) X_k / Π_(i>k) X_k + // (basically leaving our own X_i out in the calculation). + // We are assuming that Xs is ordered already. + Y := Curve.Identity() + found := false + for _, X := range Xs { + if !found && X.Equal(b.Stage.X) { + found = true + continue + } + if !found { + Y = Y.Mul(X) + } else { + Y = Y.Div(X) + } + } + if !found { + panic("own X not found in Xs") + } + + r = &StageReveal{Y: Y} + + if prev_true && b.IsSet() { + r.Z = s.R.Exp(s.x) + s.Sent = true + } else { + r.Z = Y.Exp(s.x) + s.Sent = false + } + + return r +} + +func (b *Bit) RevealStage1(Xs ...*Point) (rev *StageReveal, pr *Stage1Proof) { + if b.Stage == nil { + b.StageCommit() + } + s := b.Stage + + var ε [2][4]*Point + var r1, r2, ρ1, ρ2, ω *Scalar + for _, s := range []**Scalar{&r1, &r2, &ρ1, &ρ2, &ω} { + *s = Curve.RandomScalar() + } + c := s.commit() + + rev = b.reveal(true, Xs...) + + if b.IsSet() { + ε[0][0] = G.Exp(r1).Mul(c.X.Exp(ω)) + ε[0][1] = G.Exp(r2).Mul(b.A.Exp(ω)) + ε[0][2] = rev.Y.Exp(r1).Mul(rev.Z.Exp(ω)) + ε[0][3] = b.B.Exp(r2).Mul(b.C.Exp(ω)) + ε[1][0] = G.Exp(ρ1) + ε[1][1] = G.Exp(ρ2) + ε[1][2] = c.R.Exp(ρ1) + ε[1][3] = b.B.Exp(ρ2) + } else { + ε[0][0] = G.Exp(r1) + ε[0][1] = G.Exp(r2) + ε[0][2] = rev.Y.Exp(r1) + ε[0][3] = b.B.Exp(r2) + ε[1][0] = G.Exp(ρ1).Mul(c.X.Exp(ω)) + ε[1][1] = G.Exp(ρ2).Mul(b.A.Exp(ω)) + ε[1][2] = c.R.Exp(ρ1).Mul(rev.Z.Exp(ω)) + ε[1][3] = b.B.Exp(ρ2).Mul(b.C.Div(G).Exp(ω)) + } + + p := []Bytes{G, b.A, b.B, b.C, c.R, c.X, rev.Y, rev.Z} + for _, ε := range ε[0] { + p = append(p, ε) + } + for _, ε := range ε[1] { + p = append(p, ε) + } + + ch := Challenge(p...) + pr = &Stage1Proof{} + + if b.IsSet() { + 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(b.α.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(b.α.Mul(pr.Ch[0])) + pr.Rho[1][0] = ρ1 + pr.Rho[1][1] = ρ2 + } + + s.StageReveal = rev + return rev, pr +} + +func (c *Commitment) VerifyStage1(sc *StageCommitment, r *StageReveal, p *Stage1Proof) bool { + var ε [2][4]*Point + + ε[0][0] = G.Exp(p.Rho[0][0]).Mul(sc.X.Exp(p.Ch[0])) + ε[0][1] = G.Exp(p.Rho[0][1]).Mul(c.A.Exp(p.Ch[0])) + ε[0][2] = r.Y.Exp(p.Rho[0][0]).Mul(r.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(sc.X.Exp(p.Ch[1])) + ε[1][1] = G.Exp(p.Rho[1][1]).Mul(c.A.Exp(p.Ch[1])) + ε[1][2] = sc.R.Exp(p.Rho[1][0]).Mul(r.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, sc.R, sc.X, r.Y, r.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) +} |