aboutsummaryrefslogtreecommitdiff
path: root/vote
diff options
context:
space:
mode:
Diffstat (limited to 'vote')
-rw-r--r--vote/vote.go233
-rw-r--r--vote/vote_test.go25
2 files changed, 0 insertions, 258 deletions
diff --git a/vote/vote.go b/vote/vote.go
deleted file mode 100644
index 97367c0..0000000
--- a/vote/vote.go
+++ /dev/null
@@ -1,233 +0,0 @@
-package vote
-
-import (
- "bytes"
- "crypto/rand"
- "crypto/sha512"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "io"
-
- curve "filippo.io/edwards25519"
-)
-
-var b64 = base64.StdEncoding.WithPadding(base64.NoPadding)
-
-type point curve.Point
-type scalar curve.Scalar
-
-// Representation of a vote (true or false) of an individual.
-// The .Commitment is sent as data for round1 of the protocol.
-type Vote struct {
- bit bool
- private struct {
- id *scalar
- x *scalar
- r *scalar
- }
-
- Commitment
-}
-
-// Commitment represents the public data sent by a participant
-// in round 1 of the protocol.
-type Commitment struct {
- Id *point `json:"index"`
- Points struct {
- X *point
- R *point
- } `json:"points"`
- Proofs struct {
- X *Proof
- R *Proof
- } `json:"proofs"`
-}
-
-// 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 {
- PV *point `json:"V"`
- Sr *scalar `json:"r"`
- Id *point `json:"id"`
-}
-
-func randomScalar(random io.Reader) (*scalar, error) {
- var buf [64]byte
- if random == nil {
- random = rand.Reader
- }
- random.Read(buf[:])
- s, e := new(curve.Scalar).SetUniformBytes(buf[:])
- return (*scalar)(s), e
-}
-
-func (s *scalar) point() *point {
- p := new(curve.Point).ScalarBaseMult((*curve.Scalar)(s))
- return (*point)(p)
-}
-
-// 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 (x *scalar) proof(id *point) (pr *Proof, e error) {
- pr = &Proof{Id: id}
-
- // choose random v
- v, e := randomScalar(nil)
- if e != nil {
- return nil, e
- }
-
- // calculate g^v
- pr.PV = v.point()
-
- // calculate g^x
- gx := x.point()
-
- // calculate h := H(g, g^v, g^x, i)
- h, e := hash(pr.PV, gx, id)
- if e != nil {
- return nil, e
- }
-
- // Calculate r := v - x*h
- xh := new(curve.Scalar).Multiply((*curve.Scalar)(x), h)
- r := new(curve.Scalar).Subtract((*curve.Scalar)(v), xh)
- pr.Sr = (*scalar)(r)
-
- return pr, nil
-}
-
-// Calculate h := H(g, g^v, g^x, i)
-func hash(gv, gx *point, id *point) (*curve.Scalar, error) {
- h512 := sha512.New()
- h512.Write(curve.NewGeneratorPoint().Bytes())
- h512.Write(((*curve.Point)(gv)).Bytes())
- h512.Write(((*curve.Point)(gx)).Bytes())
- h512.Write(((*curve.Point)(id)).Bytes())
- hb := h512.Sum(nil)
- return new(curve.Scalar).SetUniformBytes(hb)
-}
-
-// Generate the proofs for both, the g^x and g^r points.
-func (v *Vote) genProofs() (e error) {
- v.Proofs.X, e = v.private.x.proof(v.Id)
- if e != nil {
- return e
- }
- v.Proofs.R, e = v.private.r.proof(v.Id)
- return e
-}
-
-// Verifies that g^v == g^r*g^(x*h)
-func verifyProof(V *point, Gx *point, r *scalar, id *point) (ok bool) {
- // Calculate h = H(g, g^v, g^x, id)
- h, e := hash(V, Gx, id)
- if e != nil {
- return false
- }
-
- // Calculate g^(x*h) = (g^x)^h
- gxh := new(curve.Point).ScalarMult(h, (*curve.Point)(Gx))
-
- // Calculate g^r
- gr := r.point()
-
- // Calculate g^r*g^(x*h)
- // Note that the edwards25519 package uses Addtion as the group
- grgxh := new(curve.Point).Add((*curve.Point)(gr), gxh)
-
- // Return true if g^v == g^r*g^(x*h)
- return ((*curve.Point)(V)).Equal(grgxh) == 1
-}
-
-func combineErr(e1, e2 error) error {
- if e1 == nil && e2 == nil {
- return nil
- } else if e1 != nil {
- if e2 == nil {
- return e1
- }
- return fmt.Errorf("%v and %v", e1, e2)
- }
- return e2
-}
-
-// Verify verifies the proofs for both, g^x and g^r
-func (v *Vote) VerifyProofs() (ok bool) {
- okX := verifyProof(v.Proofs.X.PV, v.Points.X, v.Proofs.X.Sr, v.Id)
- okR := verifyProof(v.Proofs.R.PV, v.Points.R, v.Proofs.R.Sr, v.Id)
- return okX && okR
-}
-
-// Generates a vote with commitments and proofs and takes the input for
-// the randomness from the given io.Reader
-func newVoteWithRand(bit bool, rand io.Reader) (vote *Vote, e error) {
- vote = &Vote{
- bit: bit,
- }
-
- vote.private.id, e = randomScalar(rand)
- if e != nil {
- return nil, e
- }
- vote.private.x, e = randomScalar(rand)
- if e != nil {
- return nil, e
- }
- vote.private.r, e = randomScalar(rand)
- if e != nil {
- return nil, e
- }
-
- vote.Commitment.Id = vote.private.id.point()
- vote.Commitment.Points.X = vote.private.x.point()
- vote.Commitment.Points.R = vote.private.r.point()
-
- e = vote.genProofs()
-
- return vote, nil
-}
-
-// NewVote generates a vote for given bit and index, taking crypt/Reader as
-// source for randomness
-func NewVote(bit bool) (vote *Vote, e error) {
- return newVoteWithRand(bit, nil)
-}
-
-func (p *point) String() string {
- return b64.EncodeToString(((*curve.Point)(p)).Bytes())
-}
-
-func (s *scalar) String() string {
- return b64.EncodeToString(((*curve.Scalar)(s)).Bytes())
-}
-
-func (s *scalar) MarshalJSON() ([]byte, error) {
- return []byte(fmt.Sprintf(`"%s"`, s)), nil
-
-}
-func (p *point) MarshalJSON() ([]byte, error) {
- return []byte(fmt.Sprintf(`"%s"`, p)), nil
-}
-
-func (c *Commitment) String() string {
- buf := &bytes.Buffer{}
- dec := json.NewEncoder(buf)
- dec.SetIndent("", " ")
- e := dec.Encode(c)
- if e != nil {
- return fmt.Sprintf("<error encoding: %v>", e)
- }
- return buf.String()
-}
diff --git a/vote/vote_test.go b/vote/vote_test.go
deleted file mode 100644
index 437dbe5..0000000
--- a/vote/vote_test.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package vote
-
-import (
- "testing"
-)
-
-func TestVoteGeneration(t *testing.T) {
-
- for i := range 100 {
- bit := i%3 == 1
- vote, e := newVoteWithRand(bit, nil)
-
- if e != nil {
- t.Fatalf("unexpected error: %v", e)
- }
- if vote.bit != bit {
- t.Fatalf("expected vote %t, but got %t", bit, vote.bit)
- }
- if !vote.VerifyProofs() {
- t.Fatalf("Proofs not correct! %+v", vote)
- }
-
- t.Logf("Generated %s\n", vote)
- }
-}