@@ 0,0 1,69 @@
+package main
+
+import (
+ "crypto/rand"
+ "math"
+ "math/big"
+)
+
+type Poly struct {
+ constant *big.Int
+ coefs []*big.Int
+}
+
+func RandomBigInt(numBytes uint, allowAllZeros bool) (*big.Int, error) {
+ randBytes := make([]byte, numBytes)
+ _, err := rand.Read(randBytes)
+ if err != nil {
+ return nil, err
+ }
+ bi := big.Int{}
+ bi.SetBytes(randBytes)
+ if bi.Cmp(big.NewInt(0)) == 0 {
+ return RandomBigInt(numBytes, allowAllZeros)
+ }
+ return bi.SetBytes(randBytes), nil
+}
+
+// creates a random polynomial of the given degree, uses at least `entropy' bits
+// of entropy for the random coefficients, and assigns the ballot to the
+// constant term
+func NewRandomPoly(degree uint, entropy uint, ballot []byte) *Poly {
+ constant := &big.Int{}
+ constant.SetBytes(ballot)
+ p := &Poly{constant, make([]*big.Int, degree)}
+
+ // number of bits per coefficient
+ numBits := uint(math.Ceil(float64(entropy)/float64(degree)))
+
+ // number of bytes per coefficient
+ numBytes := numBits / 8
+ if numBits % 8 > 0 {
+ numBytes += 1
+ }
+
+ var err error
+ for i := range p.coefs {
+ p.coefs[i], err = RandomBigInt(numBytes, false)
+ if err != nil {
+ panic(err)
+ }
+ }
+
+ return p
+}
+
+func (p *Poly) Eval(input *big.Int) *big.Int {
+ res := &big.Int{}
+ res.Set(p.constant)
+
+ for i, coef := range p.coefs {
+ degree := big.NewInt(int64(i+1))
+ term := &big.Int{}
+ term.Exp(input, degree, nil)
+ term.Mul(term, coef)
+ res.Add(res, term)
+ }
+
+ return res
+}