aboutsummaryrefslogblamecommitdiffstats
path: root/crypto/bn256/cloudflare/gfp2.go
blob: 90a89e8b47c66a5a47266022583814f76f283592 (plain) (tree)



























































































































































                                                                                 
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.
type gfP2 struct {
    x, y gfP // value is xi+y.
}

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) 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 = *newGFp(1)
    return e
}

func (e *gfP2) IsZero() bool {
    zero := gfP{0}
    return e.x == zero && e.y == zero
}

func (e *gfP2) IsOne() bool {
    zero, one := gfP{0}, *newGFp(1)
    return e.x == zero && e.y == one
}

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
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)
    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+9 and then returns e.
func (e *gfP2) MulXi(a *gfP2) *gfP2 {
    // (xi+y)(i+9) = (9x+y)i+(9y-x)
    tx := &gfP{}
    gfpAdd(tx, &a.x, &a.x)
    gfpAdd(tx, tx, tx)
    gfpAdd(tx, tx, tx)
    gfpAdd(tx, tx, &a.x)

    gfpAdd(tx, tx, &a.y)

    ty := &gfP{}
    gfpAdd(ty, &a.y, &a.y)
    gfpAdd(ty, ty, ty)
    gfpAdd(ty, ty, ty)
    gfpAdd(ty, ty, &a.y)

    gfpSub(ty, ty, &a.x)

    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
    tx, ty := &gfP{}, &gfP{}
    gfpSub(tx, &a.y, &a.x)
    gfpAdd(ty, &a.x, &a.y)
    gfpMul(ty, tx, ty)

    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)
    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
}