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 /commit.go | |
parent | 32cee46e39527a09504615b822cc61969c46184d (diff) |
Diffstat (limited to 'commit.go')
-rw-r--r-- | commit.go | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/commit.go b/commit.go new file mode 100644 index 0000000..eaf42e9 --- /dev/null +++ b/commit.go @@ -0,0 +1,150 @@ +package seal + +import ( + . "kesim.org/seal/common" + "kesim.org/seal/schnorr" +) + +type Bit struct { + id Bytes + set bool + α *Scalar + β *Scalar + + *Commitment + Proof *Proof + + *Stage +} + +type Commitment struct { + A *Point // g^α + B *Point // g^β + C *Point // g^(ab)g^(set) +} + +// 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 Proof struct { + 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 NewBit(id Bytes, set bool) *Bit { + α, β := Curve.RandomScalar(), Curve.RandomScalar() + return NewBitFromScalars(id, set, α, β) +} + +func NewBitFromScalars(id Bytes, set bool, α, β *Scalar) *Bit { + b := &Bit{ + id: id, + set: set, + α: α, + β: β, + } + b.commit() + b.proof() + return b +} + +func Int2Bits(id Bytes, val int, bitlength int) []*Bit { + if bitlength < 0 || bitlength > 32 { + return nil + } + + bits := make([]*Bit, bitlength) + for i := range bitlength { + bits[i] = NewBit(id, (val>>(bitlength-i-1))&1 != 0) + } + return bits +} + +func (b *Bit) IsSet() bool { + return b.set +} + +func (b *Bit) commit() { + if b.Commitment != nil { + return + } + + var C *Point + c := b.α.Mul(b.β) + + if b.set { + C = G.Exp(c.Add(One)) + } else { + C = G.Exp(c) + } + b.Commitment = &Commitment{ + C: C, + A: G.Exp(b.α), + B: G.Exp(b.β), + } +} + +func (s *Bit) proof() { + if s.Proof != nil { + return + } + + var e [2][2]*Point + var r1, r2, w *Scalar + r1 = Curve.RandomScalar() + r2 = Curve.RandomScalar() + w = Curve.RandomScalar() + s.commit() + c := s.Commitment + + if s.set { + 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], s.id) + pr := &Proof{} + + if s.set { + 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(s.id) + pr.B = (*schnorr.Statement)(s.β).Proof(s.id) + + s.Proof = pr +} + +func (c *Commitment) Verify(id Bytes, 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], id) + return p.C.Ch[0].Add(p.C.Ch[1]).Equal(ch) && + (*schnorr.Commitment)(c.A).Verify(p.A, id) && + (*schnorr.Commitment)(c.B).Verify(p.B, id) +} |