mirror of
https://github.com/sonr-io/crypto.git
synced 2026-08-02 15:31:38 +00:00
No commit suggestions generated
This commit is contained in:
Executable
+254
@@ -0,0 +1,254 @@
|
||||
package bls12381
|
||||
|
||||
const coefficientsG2 = 68
|
||||
|
||||
type Engine struct {
|
||||
pairs []pair
|
||||
}
|
||||
|
||||
type pair struct {
|
||||
g1 G1
|
||||
g2 G2
|
||||
}
|
||||
|
||||
type g2Prepared struct {
|
||||
identity int
|
||||
coefficients []coefficients
|
||||
}
|
||||
|
||||
type coefficients struct {
|
||||
a, b, c fp2
|
||||
}
|
||||
|
||||
func (c *coefficients) CMove(arg1, arg2 *coefficients, choice int) *coefficients {
|
||||
c.a.CMove(&arg1.a, &arg2.a, choice)
|
||||
c.b.CMove(&arg1.b, &arg2.b, choice)
|
||||
c.c.CMove(&arg1.c, &arg2.c, choice)
|
||||
return c
|
||||
}
|
||||
|
||||
// AddPair adds a pair of points to be paired
|
||||
func (e *Engine) AddPair(g1 *G1, g2 *G2) *Engine {
|
||||
var p pair
|
||||
p.g1.ToAffine(g1)
|
||||
p.g2.ToAffine(g2)
|
||||
if p.g1.IsIdentity()|p.g2.IsIdentity() == 0 {
|
||||
e.pairs = append(e.pairs, p)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// AddPairInvG1 adds a pair of points to be paired. G1 point is negated
|
||||
func (e *Engine) AddPairInvG1(g1 *G1, g2 *G2) *Engine {
|
||||
var p G1
|
||||
p.Neg(g1)
|
||||
return e.AddPair(&p, g2)
|
||||
}
|
||||
|
||||
// AddPairInvG2 adds a pair of points to be paired. G2 point is negated
|
||||
func (e *Engine) AddPairInvG2(g1 *G1, g2 *G2) *Engine {
|
||||
var p G2
|
||||
p.Neg(g2)
|
||||
return e.AddPair(g1, &p)
|
||||
}
|
||||
|
||||
func (e *Engine) Reset() *Engine {
|
||||
e.pairs = []pair{}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Engine) Check() bool {
|
||||
return e.pairing().IsOne() == 1
|
||||
}
|
||||
|
||||
func (e *Engine) Result() *Gt {
|
||||
return e.pairing()
|
||||
}
|
||||
|
||||
func (e *Engine) pairing() *Gt {
|
||||
f := new(Gt).SetOne()
|
||||
if len(e.pairs) == 0 {
|
||||
return f
|
||||
}
|
||||
coeffs := e.computeCoeffs()
|
||||
e.millerLoop((*fp12)(f), coeffs)
|
||||
return f.FinalExponentiation(f)
|
||||
}
|
||||
|
||||
func (e *Engine) millerLoop(f *fp12, coeffs []g2Prepared) {
|
||||
newF := new(fp12).SetZero()
|
||||
found := 0
|
||||
cIdx := 0
|
||||
for i := 63; i >= 0; i-- {
|
||||
x := int(((paramX >> 1) >> i) & 1)
|
||||
if found == 0 {
|
||||
found |= x
|
||||
continue
|
||||
}
|
||||
|
||||
// doubling
|
||||
for j, terms := range coeffs {
|
||||
identity := e.pairs[j].g1.IsIdentity() | terms.identity
|
||||
newF.Set(f)
|
||||
ell(newF, terms.coefficients[cIdx], &e.pairs[j].g1)
|
||||
f.CMove(newF, f, identity)
|
||||
}
|
||||
cIdx++
|
||||
|
||||
if x == 1 {
|
||||
// adding
|
||||
for j, terms := range coeffs {
|
||||
identity := e.pairs[j].g1.IsIdentity() | terms.identity
|
||||
newF.Set(f)
|
||||
ell(newF, terms.coefficients[cIdx], &e.pairs[j].g1)
|
||||
f.CMove(newF, f, identity)
|
||||
}
|
||||
cIdx++
|
||||
}
|
||||
f.Square(f)
|
||||
}
|
||||
for j, terms := range coeffs {
|
||||
identity := e.pairs[j].g1.IsIdentity() | terms.identity
|
||||
newF.Set(f)
|
||||
ell(newF, terms.coefficients[cIdx], &e.pairs[j].g1)
|
||||
f.CMove(newF, f, identity)
|
||||
}
|
||||
f.Conjugate(f)
|
||||
}
|
||||
|
||||
func (e *Engine) computeCoeffs() []g2Prepared {
|
||||
coeffs := make([]g2Prepared, len(e.pairs))
|
||||
for i, p := range e.pairs {
|
||||
identity := p.g2.IsIdentity()
|
||||
q := new(G2).Generator()
|
||||
q.CMove(&p.g2, q, identity)
|
||||
c := new(G2).Set(q)
|
||||
cfs := make([]coefficients, coefficientsG2)
|
||||
found := 0
|
||||
k := 0
|
||||
|
||||
for j := 63; j >= 0; j-- {
|
||||
x := int(((paramX >> 1) >> j) & 1)
|
||||
if found == 0 {
|
||||
found |= x
|
||||
continue
|
||||
}
|
||||
cfs[k] = doublingStep(c)
|
||||
k++
|
||||
|
||||
if x == 1 {
|
||||
cfs[k] = additionStep(c, q)
|
||||
k++
|
||||
}
|
||||
}
|
||||
cfs[k] = doublingStep(c)
|
||||
coeffs[i] = g2Prepared{
|
||||
coefficients: cfs, identity: identity,
|
||||
}
|
||||
}
|
||||
return coeffs
|
||||
}
|
||||
|
||||
func ell(f *fp12, coeffs coefficients, p *G1) {
|
||||
var x, y fp2
|
||||
x.A.Mul(&coeffs.a.A, &p.y)
|
||||
x.B.Mul(&coeffs.a.B, &p.y)
|
||||
y.A.Mul(&coeffs.b.A, &p.x)
|
||||
y.B.Mul(&coeffs.b.B, &p.x)
|
||||
f.MulByABD(f, &coeffs.c, &y, &x)
|
||||
}
|
||||
|
||||
func doublingStep(p *G2) coefficients {
|
||||
// Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
|
||||
var t0, t1, t2, t3, t4, t5, t6, zsqr fp2
|
||||
t0.Square(&p.x)
|
||||
t1.Square(&p.y)
|
||||
t2.Square(&t1)
|
||||
t3.Add(&t1, &p.x)
|
||||
t3.Square(&t3)
|
||||
t3.Sub(&t3, &t0)
|
||||
t3.Sub(&t3, &t2)
|
||||
t3.Double(&t3)
|
||||
t4.Double(&t0)
|
||||
t4.Add(&t4, &t0)
|
||||
t6.Add(&p.x, &t4)
|
||||
t5.Square(&t4)
|
||||
zsqr.Square(&p.z)
|
||||
p.x.Sub(&t5, &t3)
|
||||
p.x.Sub(&p.x, &t3)
|
||||
p.z.Add(&p.z, &p.y)
|
||||
p.z.Square(&p.z)
|
||||
p.z.Sub(&p.z, &t1)
|
||||
p.z.Sub(&p.z, &zsqr)
|
||||
p.y.Sub(&t3, &p.x)
|
||||
p.y.Mul(&p.y, &t4)
|
||||
t2.Double(&t2)
|
||||
t2.Double(&t2)
|
||||
t2.Double(&t2)
|
||||
p.y.Sub(&p.y, &t2)
|
||||
t3.Mul(&t4, &zsqr)
|
||||
t3.Double(&t3)
|
||||
t3.Neg(&t3)
|
||||
t6.Square(&t6)
|
||||
t6.Sub(&t6, &t0)
|
||||
t6.Sub(&t6, &t5)
|
||||
t1.Double(&t1)
|
||||
t1.Double(&t1)
|
||||
t6.Sub(&t6, &t1)
|
||||
t0.Mul(&p.z, &zsqr)
|
||||
t0.Double(&t0)
|
||||
|
||||
return coefficients{
|
||||
a: t0, b: t3, c: t6,
|
||||
}
|
||||
}
|
||||
|
||||
func additionStep(r, q *G2) coefficients {
|
||||
// Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
|
||||
var zsqr, ysqr fp2
|
||||
var t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10 fp2
|
||||
zsqr.Square(&r.z)
|
||||
ysqr.Square(&q.y)
|
||||
t0.Mul(&zsqr, &q.x)
|
||||
t1.Add(&q.y, &r.z)
|
||||
t1.Square(&t1)
|
||||
t1.Sub(&t1, &ysqr)
|
||||
t1.Sub(&t1, &zsqr)
|
||||
t1.Mul(&t1, &zsqr)
|
||||
t2.Sub(&t0, &r.x)
|
||||
t3.Square(&t2)
|
||||
t4.Double(&t3)
|
||||
t4.Double(&t4)
|
||||
t5.Mul(&t4, &t2)
|
||||
t6.Sub(&t1, &r.y)
|
||||
t6.Sub(&t6, &r.y)
|
||||
t9.Mul(&t6, &q.x)
|
||||
t7.Mul(&t4, &r.x)
|
||||
r.x.Square(&t6)
|
||||
r.x.Sub(&r.x, &t5)
|
||||
r.x.Sub(&r.x, &t7)
|
||||
r.x.Sub(&r.x, &t7)
|
||||
r.z.Add(&r.z, &t2)
|
||||
r.z.Square(&r.z)
|
||||
r.z.Sub(&r.z, &zsqr)
|
||||
r.z.Sub(&r.z, &t3)
|
||||
t10.Add(&q.y, &r.z)
|
||||
t8.Sub(&t7, &r.x)
|
||||
t8.Mul(&t8, &t6)
|
||||
t0.Mul(&r.y, &t5)
|
||||
t0.Double(&t0)
|
||||
r.y.Sub(&t8, &t0)
|
||||
t10.Square(&t10)
|
||||
t10.Sub(&t10, &ysqr)
|
||||
zsqr.Square(&r.z)
|
||||
t10.Sub(&t10, &zsqr)
|
||||
t9.Double(&t9)
|
||||
t9.Sub(&t9, &t10)
|
||||
t10.Double(&r.z)
|
||||
t6.Neg(&t6)
|
||||
t1.Double(&t6)
|
||||
|
||||
return coefficients{
|
||||
a: t10, b: t1, c: t9,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user