wormhole/bridge/third_party/chainlink/secp256k1/field.go

170 lines
5.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package secp256k1 is an implementation of the kyber.{Group,Point,Scalar}
////////////////////////////////////////////////////////////////////////////////
// XXX: Do not use in production until this code has been audited.
////////////////////////////////////////////////////////////////////////////////
// interfaces, based on btcd/btcec and kyber/group/mod
//
// XXX: NOT CONSTANT TIME!
package secp256k1
// Arithmetic operations in the base field of secp256k1, i.e. /q, where q is
// the base field characteristic.
import (
"crypto/cipher"
"fmt"
"math/big"
"go.dedis.ch/kyber/v3/util/random"
)
// q is the field characteristic (cardinality) of the secp256k1 base field. All
// arithmetic operations on the field are modulo this.
var q = s256.P
type fieldElt big.Int
// newFieldZero returns a newly allocated field element.
func newFieldZero() *fieldElt { return (*fieldElt)(big.NewInt(0)) }
// Int returns f as a big.Int
func (f *fieldElt) Int() *big.Int { return (*big.Int)(f) }
// modQ reduces f's underlying big.Int modulo q, and returns it
func (f *fieldElt) modQ() *fieldElt {
if f.Int().Cmp(q) != -1 || f.Int().Cmp(bigZero) == -1 {
// f ∉ {0, ..., q-1}. Find the representative of f+q in that set.
//
// Per Mod docstring, "Mod implements Euclidean modulus", meaning that after
// this, f will be the smallest non-negative representative of its
// equivalence class in /q. TODO(alx): Make this faster
f.Int().Mod(f.Int(), q)
}
return f
}
// This differs from SetInt below, in that it does not take a copy of v.
func fieldEltFromBigInt(v *big.Int) *fieldElt { return (*fieldElt)(v).modQ() }
func fieldEltFromInt(v int64) *fieldElt {
return fieldEltFromBigInt(big.NewInt(int64(v))).modQ()
}
var fieldZero = fieldEltFromInt(0)
var bigZero = big.NewInt(0)
// String returns the string representation of f
func (f *fieldElt) String() string {
return fmt.Sprintf("fieldElt{%x}", f.Int())
}
// Equal returns true iff f=g, i.e. the backing big.Ints satisfy f ≡ g mod q
func (f *fieldElt) Equal(g *fieldElt) bool {
if f == (*fieldElt)(nil) && g == (*fieldElt)(nil) {
return true
}
if f == (*fieldElt)(nil) { // f is nil, g is not
return false
}
if g == (*fieldElt)(nil) { // g is nil, f is not
return false
}
return bigZero.Cmp(newFieldZero().Sub(f, g).modQ().Int()) == 0
}
// Add sets f to the sum of a and b modulo q, and returns it.
func (f *fieldElt) Add(a, b *fieldElt) *fieldElt {
f.Int().Add(a.Int(), b.Int())
return f.modQ()
}
// Sub sets f to a-b mod q, and returns it.
func (f *fieldElt) Sub(a, b *fieldElt) *fieldElt {
f.Int().Sub(a.Int(), b.Int())
return f.modQ()
}
// Set sets f's value to v, and returns f.
func (f *fieldElt) Set(v *fieldElt) *fieldElt {
f.Int().Set(v.Int())
return f.modQ()
}
// SetInt sets f's value to v mod q, and returns f.
func (f *fieldElt) SetInt(v *big.Int) *fieldElt {
f.Int().Set(v)
return f.modQ()
}
// Pick samples uniformly from {0, ..., q-1}, assigns sample to f, and returns f
func (f *fieldElt) Pick(rand cipher.Stream) *fieldElt {
return f.SetInt(random.Int(q, rand)) // random.Int safe because q≅2²⁵⁶, q<2²⁵⁶
}
// Neg sets f to the negation of g modulo q, and returns it
func (f *fieldElt) Neg(g *fieldElt) *fieldElt {
f.Int().Neg(g.Int())
return f.modQ()
}
// Clone returns a new fieldElt, backed by a clone of f
func (f *fieldElt) Clone() *fieldElt { return newFieldZero().Set(f.modQ()) }
// SetBytes sets f to the 32-byte big-endian value represented by buf, reduces
// it, and returns it.
func (f *fieldElt) SetBytes(buf [32]byte) *fieldElt {
f.Int().SetBytes(buf[:])
return f.modQ()
}
// Bytes returns the 32-byte big-endian representation of f
func (f *fieldElt) Bytes() [32]byte {
bytes := f.modQ().Int().Bytes()
if len(bytes) > 32 {
panic("field element longer than 256 bits")
}
var rv [32]byte
copy(rv[32-len(bytes):], bytes) // leftpad w zeros
return rv
}
var two = big.NewInt(2)
// square returns y² mod q
func fieldSquare(y *fieldElt) *fieldElt {
return fieldEltFromBigInt(newFieldZero().Int().Exp(y.Int(), two, q))
}
// sqrtPower is s.t. n^sqrtPower≡sqrt(n) mod q, if n has a root at all. See
// https://math.stackexchange.com/a/1816280, for instance
//
// What I'm calling sqrtPower is called q on the s256 struct. (See
// btcec.initS256), which is confusing because the "Q" in "QPlus1Div4" refers to
// the field characteristic
var sqrtPower = s256.QPlus1Div4()
// maybeSqrtInField returns a square root of v, if it has any, else nil
func maybeSqrtInField(v *fieldElt) *fieldElt {
s := newFieldZero()
s.Int().Exp(v.Int(), sqrtPower, q)
if !fieldSquare(s).Equal(v) {
return nil
}
return s
}
var three = big.NewInt(3)
var seven = fieldEltFromInt(7)
// rightHandSide returns the RHS of the secp256k1 equation, x³+7 mod q, given x
func rightHandSide(x *fieldElt) *fieldElt {
xCubed := newFieldZero()
xCubed.Int().Exp(x.Int(), three, q)
return xCubed.Add(xCubed, seven)
}
// isEven returns true if f is even, false otherwise
func (f *fieldElt) isEven() bool {
return big.NewInt(0).Mod(f.Int(), two).Cmp(big.NewInt(0)) == 0
}