diff options
Diffstat (limited to 'vote/vote.go')
| -rw-r--r-- | vote/vote.go | 233 | 
1 files changed, 0 insertions, 233 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() -}  | 
