mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-04 18:31:41 +00:00
(no commit message provided)
This commit is contained in:
committed by
Prad Nukala (aider)
parent
5fd43dfd6b
commit
2f976209db
@@ -1,344 +0,0 @@
|
||||
package bls12381
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// fp2 is a point in p^2
|
||||
type fp2 struct {
|
||||
A, B fp
|
||||
}
|
||||
|
||||
// Set copies a into fp2
|
||||
func (f *fp2) Set(a *fp2) *fp2 {
|
||||
f.A.Set(&a.A)
|
||||
f.B.Set(&a.B)
|
||||
return f
|
||||
}
|
||||
|
||||
// SetZero fp2 = 0
|
||||
func (f *fp2) SetZero() *fp2 {
|
||||
f.A.SetZero()
|
||||
f.B.SetZero()
|
||||
return f
|
||||
}
|
||||
|
||||
// SetOne fp2 to the multiplicative identity element
|
||||
func (f *fp2) SetOne() *fp2 {
|
||||
f.A.SetOne()
|
||||
f.B.SetZero()
|
||||
return f
|
||||
}
|
||||
|
||||
// SetFp creates an element from a lower field
|
||||
func (f *fp2) SetFp(a *fp) *fp2 {
|
||||
f.A.Set(a)
|
||||
f.B.SetZero()
|
||||
return f
|
||||
}
|
||||
|
||||
// Random generates a random field element
|
||||
func (f *fp2) Random(reader io.Reader) (*fp2, error) {
|
||||
a, err := new(fp).Random(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := new(fp).Random(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.A = *a
|
||||
f.B = *b
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// IsZero returns 1 if fp2 == 0, 0 otherwise
|
||||
func (f *fp2) IsZero() int {
|
||||
return f.A.IsZero() & f.B.IsZero()
|
||||
}
|
||||
|
||||
// IsOne returns 1 if fp2 == 1, 0 otherwise
|
||||
func (f *fp2) IsOne() int {
|
||||
return f.A.IsOne() & f.B.IsZero()
|
||||
}
|
||||
|
||||
// Equal returns 1 if f == rhs, 0 otherwise
|
||||
func (f *fp2) Equal(rhs *fp2) int {
|
||||
return f.A.Equal(&rhs.A) & f.B.Equal(&rhs.B)
|
||||
}
|
||||
|
||||
// LexicographicallyLargest returns 1 if
|
||||
// this element is strictly lexicographically larger than its negation
|
||||
// 0 otherwise
|
||||
func (f *fp2) LexicographicallyLargest() int {
|
||||
// If this element's B coefficient is lexicographically largest
|
||||
// then it is lexicographically largest. Otherwise, in the event
|
||||
// the B coefficient is zero and the A coefficient is
|
||||
// lexicographically largest, then this element is lexicographically
|
||||
// largest.
|
||||
|
||||
return f.B.LexicographicallyLargest() |
|
||||
f.B.IsZero()&f.A.LexicographicallyLargest()
|
||||
}
|
||||
|
||||
// Sgn0 returns the lowest bit value
|
||||
func (f *fp2) Sgn0() int {
|
||||
// if A = 0 return B.Sgn0 else A.Sgn0
|
||||
a := f.A.IsZero()
|
||||
t := f.B.Sgn0() & a
|
||||
a = -a + 1
|
||||
t |= f.A.Sgn0() & a
|
||||
return t
|
||||
}
|
||||
|
||||
// FrobeniusMap raises this element to p.
|
||||
func (f *fp2) FrobeniusMap(a *fp2) *fp2 {
|
||||
// This is always just a conjugation. If you're curious why, here's
|
||||
// an article about it: https://alicebob.cryptoland.net/the-frobenius-endomorphism-with-finite-fields/
|
||||
return f.Conjugate(a)
|
||||
}
|
||||
|
||||
// Conjugate computes the conjugation of this element
|
||||
func (f *fp2) Conjugate(a *fp2) *fp2 {
|
||||
f.A.Set(&a.A)
|
||||
f.B.Neg(&a.B)
|
||||
return f
|
||||
}
|
||||
|
||||
// MulByNonResidue computes the following:
|
||||
// multiply a + bu by u + 1, getting
|
||||
// au + a + bu^2 + bu
|
||||
// and because u^2 = -1, we get
|
||||
// (a - b) + (a + b)u
|
||||
func (f *fp2) MulByNonResidue(a *fp2) *fp2 {
|
||||
var aa, bb fp
|
||||
aa.Sub(&a.A, &a.B)
|
||||
bb.Add(&a.A, &a.B)
|
||||
f.A.Set(&aa)
|
||||
f.B.Set(&bb)
|
||||
return f
|
||||
}
|
||||
|
||||
// Square computes the square of this element
|
||||
func (f *fp2) Square(arg *fp2) *fp2 {
|
||||
var a, b, c fp
|
||||
|
||||
// Complex squaring:
|
||||
//
|
||||
// v0 = a * b
|
||||
// a' = (a + b) * (a + \beta*b) - v0 - \beta * v0
|
||||
// b' = 2 * v0
|
||||
//
|
||||
// In BLS12-381's F_{p^2}, our \beta is -1, so we
|
||||
// can modify this formula:
|
||||
//
|
||||
// a' = (a + b) * (a - b)
|
||||
// b' = 2 * a * b
|
||||
a.Add(&arg.A, &arg.B)
|
||||
b.Sub(&arg.A, &arg.B)
|
||||
c.Add(&arg.A, &arg.A)
|
||||
|
||||
f.A.Mul(&a, &b)
|
||||
f.B.Mul(&c, &arg.B)
|
||||
return f
|
||||
}
|
||||
|
||||
// Add performs field addition
|
||||
func (f *fp2) Add(arg1, arg2 *fp2) *fp2 {
|
||||
f.A.Add(&arg1.A, &arg2.A)
|
||||
f.B.Add(&arg1.B, &arg2.B)
|
||||
return f
|
||||
}
|
||||
|
||||
// Double doubles specified element
|
||||
func (f *fp2) Double(a *fp2) *fp2 {
|
||||
f.A.Double(&a.A)
|
||||
f.B.Double(&a.B)
|
||||
return f
|
||||
}
|
||||
|
||||
// Sub performs field subtraction
|
||||
func (f *fp2) Sub(arg1, arg2 *fp2) *fp2 {
|
||||
f.A.Sub(&arg1.A, &arg2.A)
|
||||
f.B.Sub(&arg1.B, &arg2.B)
|
||||
return f
|
||||
}
|
||||
|
||||
// Mul computes Karatsuba multiplication
|
||||
func (f *fp2) Mul(arg1, arg2 *fp2) *fp2 {
|
||||
var v0, v1, t, a, b fp
|
||||
|
||||
// Karatsuba multiplication:
|
||||
//
|
||||
// v0 = a0 * b0
|
||||
// v1 = a1 * b1
|
||||
// c0 = v0 + \beta * v1
|
||||
// c1 = (a0 + a1) * (b0 + b1) - v0 - v1
|
||||
//
|
||||
// In BLS12-381's F_{p^2}, our \beta is -1, so we
|
||||
// can modify this formula. (Also, since we always
|
||||
// subtract v1, we can compute v1 = -a1 * b1.)
|
||||
//
|
||||
// v0 = a0 * a1
|
||||
// v1 = (-b0) * b1
|
||||
// a' = v0 + v1
|
||||
// b' = (a0 + b0) * (a1 + b1) - v0 + v1
|
||||
v0.Mul(&arg1.A, &arg2.A)
|
||||
v1.Mul(new(fp).Neg(&arg1.B), &arg2.B)
|
||||
|
||||
a.Add(&v0, &v1)
|
||||
b.Add(&arg1.A, &arg1.B)
|
||||
t.Add(&arg2.A, &arg2.B)
|
||||
b.Mul(&b, &t)
|
||||
b.Sub(&b, &v0)
|
||||
b.Add(&b, &v1)
|
||||
f.A.Set(&a)
|
||||
f.B.Set(&b)
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *fp2) Mul0(arg1 *fp2, arg2 *fp) *fp2 {
|
||||
f.A.Mul(&arg1.A, arg2)
|
||||
f.B.Mul(&arg1.B, arg2)
|
||||
return f
|
||||
}
|
||||
|
||||
// MulBy3b returns arg * 12 or 3 * b
|
||||
func (f *fp2) MulBy3b(arg *fp2) *fp2 {
|
||||
return f.Mul(arg, &curveG23B)
|
||||
}
|
||||
|
||||
// Neg performs field negation
|
||||
func (f *fp2) Neg(a *fp2) *fp2 {
|
||||
f.A.Neg(&a.A)
|
||||
f.B.Neg(&a.B)
|
||||
return f
|
||||
}
|
||||
|
||||
// Sqrt performs field square root
|
||||
func (f *fp2) Sqrt(a *fp2) (*fp2, int) {
|
||||
// Algorithm 9, https://eprint.iacr.org/2012/685.pdf
|
||||
// with constant time modifications.
|
||||
var a1, alpha, x0, t, res, res2 fp2
|
||||
e1 := a.IsZero()
|
||||
// a1 = self^((p - 3) / 4)
|
||||
a1.pow(a, &[Limbs]uint64{
|
||||
0xee7fbfffffffeaaa,
|
||||
0x07aaffffac54ffff,
|
||||
0xd9cc34a83dac3d89,
|
||||
0xd91dd2e13ce144af,
|
||||
0x92c6e9ed90d2eb35,
|
||||
0x0680447a8e5ff9a6,
|
||||
})
|
||||
|
||||
// alpha = a1^2 * a = a^((p - 3) / 2 + 1) = a^((p - 1) / 2)
|
||||
alpha.Square(&a1)
|
||||
alpha.Mul(&alpha, a)
|
||||
|
||||
// x0 = self^((p + 1) / 4)
|
||||
x0.Mul(&a1, a)
|
||||
|
||||
// In the event that alpha = -1, the element is order p - 1. So
|
||||
// we're just trying to get the square of an element of the subfield
|
||||
// fp. This is given by x0 * u, since u = sqrt(-1). Since the element
|
||||
// x0 = a + bu has b = 0, the solution is therefore au.
|
||||
res2.A.Neg(&x0.B)
|
||||
res2.B.Set(&x0.A)
|
||||
// alpha == -1
|
||||
e2 := alpha.Equal(&fp2{
|
||||
A: fp{
|
||||
0x43f5fffffffcaaae,
|
||||
0x32b7fff2ed47fffd,
|
||||
0x07e83a49a2e99d69,
|
||||
0xeca8f3318332bb7a,
|
||||
0xef148d1ea0f4c069,
|
||||
0x040ab3263eff0206,
|
||||
},
|
||||
B: fp{},
|
||||
})
|
||||
|
||||
// Otherwise, the correct solution is (1 + alpha)^((p - 1) // 2) * x0
|
||||
t.SetOne()
|
||||
t.Add(&t, &alpha)
|
||||
t.pow(&t, &[Limbs]uint64{
|
||||
0xdcff7fffffffd555,
|
||||
0x0f55ffff58a9ffff,
|
||||
0xb39869507b587b12,
|
||||
0xb23ba5c279c2895f,
|
||||
0x258dd3db21a5d66b,
|
||||
0x0d0088f51cbff34d,
|
||||
})
|
||||
t.Mul(&t, &x0)
|
||||
// if a = 0, then its zero
|
||||
res.CMove(&res2, &res, e1)
|
||||
// if alpha = -1, its not (1 + alpha)^((p - 1) // 2) * x0
|
||||
// but au
|
||||
res.CMove(&t, &res, e2)
|
||||
|
||||
// is the result^2 = a
|
||||
t.Square(&res)
|
||||
e3 := t.Equal(a)
|
||||
f.CMove(f, &res, e3)
|
||||
return f, e3
|
||||
}
|
||||
|
||||
// Invert computes the multiplicative inverse of this field
|
||||
// element, returning the original value of fp2
|
||||
// in the case that this element is zero.
|
||||
func (f *fp2) Invert(arg *fp2) (*fp2, int) {
|
||||
// We wish to find the multiplicative inverse of a nonzero
|
||||
// element a + bu in fp2. We leverage an identity
|
||||
//
|
||||
// (a + bu)(a - bu) = a^2 + b^2
|
||||
//
|
||||
// which holds because u^2 = -1. This can be rewritten as
|
||||
//
|
||||
// (a + bu)(a - bu)/(a^2 + b^2) = 1
|
||||
//
|
||||
// because a^2 + b^2 = 0 has no nonzero solutions for (a, b).
|
||||
// This gives that (a - bu)/(a^2 + b^2) is the inverse
|
||||
// of (a + bu). Importantly, this can be computing using
|
||||
// only a single inversion in fp.
|
||||
var a, b, t fp
|
||||
a.Square(&arg.A)
|
||||
b.Square(&arg.B)
|
||||
a.Add(&a, &b)
|
||||
_, wasInverted := t.Invert(&a)
|
||||
// a * t
|
||||
a.Mul(&arg.A, &t)
|
||||
// b * -t
|
||||
b.Neg(&t)
|
||||
b.Mul(&b, &arg.B)
|
||||
f.A.CMove(&f.A, &a, wasInverted)
|
||||
f.B.CMove(&f.B, &b, wasInverted)
|
||||
return f, wasInverted
|
||||
}
|
||||
|
||||
// CMove performs conditional select.
|
||||
// selects arg1 if choice == 0 and arg2 if choice == 1
|
||||
func (f *fp2) CMove(arg1, arg2 *fp2, choice int) *fp2 {
|
||||
f.A.CMove(&arg1.A, &arg2.A, choice)
|
||||
f.B.CMove(&arg1.B, &arg2.B, choice)
|
||||
return f
|
||||
}
|
||||
|
||||
// CNeg conditionally negates a if choice == 1
|
||||
func (f *fp2) CNeg(a *fp2, choice int) *fp2 {
|
||||
var t fp2
|
||||
t.Neg(a)
|
||||
return f.CMove(f, &t, choice)
|
||||
}
|
||||
|
||||
func (f *fp2) pow(base *fp2, exp *[Limbs]uint64) *fp2 {
|
||||
res := (&fp2{}).SetOne()
|
||||
tmp := (&fp2{}).SetZero()
|
||||
|
||||
for i := len(exp) - 1; i >= 0; i-- {
|
||||
for j := 63; j >= 0; j-- {
|
||||
res.Square(res)
|
||||
tmp.Mul(res, base)
|
||||
res.CMove(res, tmp, int(exp[i]>>j)&1)
|
||||
}
|
||||
}
|
||||
return f.Set(res)
|
||||
}
|
||||
Reference in New Issue
Block a user