From bde2442514d08f1aa4299f52886eb0ad3cfd7f9f Mon Sep 17 00:00:00 2001 From: David Florness Date: Sun, 7 Jun 2020 14:40:55 -0600 Subject: [PATCH] Polynomials --- poly.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 poly.go diff --git a/poly.go b/poly.go new file mode 100644 index 0000000..8ebf89c --- /dev/null +++ b/poly.go @@ -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 +} -- 2.38.4