init: v1.0.0
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
package bn256
|
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
// gfP2 implements a field of size P² as a quadratic extension of the base field
|
||||
// where i²=-1.
|
||||
// For SM9, gfP2 = gfP[x]/(x²+2) = gfP(u) where u²=-2.
|
||||
type gfP2 struct {
|
||||
// sm9: xu+y
|
||||
x, y gfP
|
||||
}
|
||||
|
||||
func gfP2Decode(in *gfP2) *gfP2 {
|
||||
out := &gfP2{}
|
||||
montDecode(&out.x, &in.x)
|
||||
montDecode(&out.y, &in.y)
|
||||
return out
|
||||
}
|
||||
|
||||
func (e *gfP2) String() string {
|
||||
return "(" + e.x.String() + ", " + e.y.String() + ")"
|
||||
}
|
||||
|
||||
func (e *gfP2) Equal(other *gfP2) bool {
|
||||
return e.x.Equal(&other.x) && e.y.Equal(&other.y)
|
||||
}
|
||||
|
||||
func (e *gfP2) Set(a *gfP2) *gfP2 {
|
||||
e.x.Set(&a.x)
|
||||
e.y.Set(&a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) SetZero() *gfP2 {
|
||||
e.x = gfP{0}
|
||||
e.y = gfP{0}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) SetOne() *gfP2 {
|
||||
e.x = gfP{0}
|
||||
e.y = gfPOne
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) IsZero() bool {
|
||||
return e.x == gfPZero && e.y == gfPZero
|
||||
}
|
||||
|
||||
func (e *gfP2) IsOne() bool {
|
||||
return e.x == gfPZero && e.y == gfPOne
|
||||
}
|
||||
|
||||
// Conjugate sets e = -xu+y if a = xu+y. Also note that conjugate equivalents to e = Frobenius(a) = a^p
|
||||
func (e *gfP2) Conjugate(a *gfP2) *gfP2 {
|
||||
e.y.Set(&a.y)
|
||||
gfpNeg(&e.x, &a.x)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Neg(a *gfP2) *gfP2 {
|
||||
gfpNeg(&e.x, &a.x)
|
||||
gfpNeg(&e.y, &a.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Add(a, b *gfP2) *gfP2 {
|
||||
gfpAdd(&e.x, &a.x, &b.x)
|
||||
gfpAdd(&e.y, &a.y, &b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Sub(a, b *gfP2) *gfP2 {
|
||||
gfpSub(&e.x, &a.x, &b.x)
|
||||
gfpSub(&e.y, &a.y, &b.y)
|
||||
return e
|
||||
}
|
||||
|
||||
// See "Multiplication and Squaring in Pairing-Friendly Fields",
|
||||
// http://eprint.iacr.org/2006/471.pdf
|
||||
// (ax*u + ay) (bx*u + by) = (ay*by - 2ax*bx) + (ay*bx+ax*by)u
|
||||
func (e *gfP2) Mul(a, b *gfP2) *gfP2 {
|
||||
tx, t := &gfP{}, &gfP{}
|
||||
gfpMul(tx, &a.x, &b.y)
|
||||
gfpMul(t, &b.x, &a.y)
|
||||
gfpAdd(tx, tx, t)
|
||||
|
||||
ty := &gfP{}
|
||||
gfpMul(ty, &a.y, &b.y)
|
||||
gfpMul(t, &a.x, &b.x)
|
||||
gfpAdd(t, t, t)
|
||||
gfpSub(ty, ty, t)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) MulScalar(a *gfP2, b *gfP) *gfP2 {
|
||||
gfpMul(&e.x, &a.x, b)
|
||||
gfpMul(&e.y, &a.y, b)
|
||||
return e
|
||||
}
|
||||
|
||||
//MulXi sets e=ξa where ξ=i+3 and then returns e.
|
||||
//e = u*a = -2x + yu
|
||||
// sm9: e = a*u = yu - 2x
|
||||
func (e *gfP2) MulXi(a *gfP2) *gfP2 {
|
||||
// (xi+y)(i+3) = (3x+y)i+(3y-x)
|
||||
//e = u*a = -2x + yu
|
||||
ty := &gfP{}
|
||||
gfpAdd(ty, &a.x, &a.x)
|
||||
gfpNeg(ty, ty)
|
||||
|
||||
tx := &gfP{}
|
||||
tx.Set(&a.y)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Square(a *gfP2) *gfP2 {
|
||||
// Complex squaring algorithm:
|
||||
// (xi+y)² = (x+y)(y-x) + 2*i*x*y
|
||||
// sm9: (xu+y)² = y²-2x² + 2uxy
|
||||
tx, ty := &gfP{}, &gfP{}
|
||||
gfpMul(ty, &a.y, &a.y)
|
||||
gfpMul(tx, &a.x, &a.x)
|
||||
gfpAdd(tx, tx, tx)
|
||||
gfpSub(ty, ty, tx)
|
||||
|
||||
gfpMul(tx, &a.x, &a.y)
|
||||
gfpAdd(tx, tx, tx)
|
||||
|
||||
e.x.Set(tx)
|
||||
e.y.Set(ty)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *gfP2) Invert(a *gfP2) *gfP2 {
|
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
t1, t2 := &gfP{}, &gfP{}
|
||||
gfpMul(t1, &a.x, &a.x)
|
||||
gfpAdd(t1, t1, t1)
|
||||
gfpMul(t2, &a.y, &a.y)
|
||||
gfpAdd(t1, t1, t2)
|
||||
|
||||
inv := &gfP{}
|
||||
inv.Invert(t1)
|
||||
|
||||
gfpNeg(t1, &a.x)
|
||||
|
||||
gfpMul(&e.x, t1, inv)
|
||||
gfpMul(&e.y, &a.y, inv)
|
||||
return e
|
||||
}
|
||||
|
||||
// Sqrt sets e = sqrt(e) and return true if e is a square. Otherwise returns false and e remain unchanged.
|
||||
// The algorithm is based on the beautiful identity:
|
||||
// $$
|
||||
// \sqrt{a+bx} = \pm\left(\sqrt{ \frac{a \pm \sqrt{a^2 + nb^2}}{2} } + \frac{xb}{2\sqrt{ \frac{a \pm \sqrt{a^2 + nb^2}}{2} }}\right)
|
||||
// $$
|
||||
func (e *gfP2) Sqrt(f *gfP2) bool {
|
||||
a := &gfP{}
|
||||
b := &gfP{}
|
||||
tmp := &gfP{}
|
||||
|
||||
// e = a + bu
|
||||
gfpMul(a, &f.y, &f.y)
|
||||
gfpMul(b, &f.x, &f.x)
|
||||
gfpAdd(tmp, a, b)
|
||||
gfpAdd(tmp, tmp, b)
|
||||
//a = a^2 + nb^2
|
||||
|
||||
if legendre(tmp) != 1 {
|
||||
return false
|
||||
}
|
||||
tmp.Sqrt(tmp)
|
||||
|
||||
gfpAdd(a, &f.y, tmp)
|
||||
a.half(a)
|
||||
if legendre(a) != 1 {
|
||||
gfpSub(a, &f.y, tmp)
|
||||
a.half(a)
|
||||
if legendre(a) != 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
e.y.Sqrt(a)
|
||||
gfpAdd(a, &e.y, &e.y)
|
||||
a.Invert(a)
|
||||
gfpMul(&e.x, a, &f.x)
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user