github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/cloudflare/gfp12.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package bn256 19 20 // For details of the algorithms used, see "Multiplication and Squaring on 21 // Pairing-Friendly Fields, Devegili et al. 22 // http://eprint.iacr.org/2006/471.pdf. 23 24 import ( 25 "math/big" 26 ) 27 28 // gfP12 implements the field of size p¹² as a quadratic extension of gfP6 29 // where ω²=τ. 30 type gfP12 struct { 31 x, y gfP6 // value is xω + y 32 } 33 34 func (e *gfP12) String() string { 35 return "(" + e.x.String() + "," + e.y.String() + ")" 36 } 37 38 func (e *gfP12) Set(a *gfP12) *gfP12 { 39 e.x.Set(&a.x) 40 e.y.Set(&a.y) 41 return e 42 } 43 44 func (e *gfP12) SetZero() *gfP12 { 45 e.x.SetZero() 46 e.y.SetZero() 47 return e 48 } 49 50 func (e *gfP12) SetOne() *gfP12 { 51 e.x.SetZero() 52 e.y.SetOne() 53 return e 54 } 55 56 func (e *gfP12) IsZero() bool { 57 return e.x.IsZero() && e.y.IsZero() 58 } 59 60 func (e *gfP12) IsOne() bool { 61 return e.x.IsZero() && e.y.IsOne() 62 } 63 64 func (e *gfP12) Conjugate(a *gfP12) *gfP12 { 65 e.x.Neg(&a.x) 66 e.y.Set(&a.y) 67 return e 68 } 69 70 func (e *gfP12) Neg(a *gfP12) *gfP12 { 71 e.x.Neg(&a.x) 72 e.y.Neg(&a.y) 73 return e 74 } 75 76 // Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p 77 func (e *gfP12) Frobenius(a *gfP12) *gfP12 { 78 e.x.Frobenius(&a.x) 79 e.y.Frobenius(&a.y) 80 e.x.MulScalar(&e.x, xiToPMinus1Over6) 81 return e 82 } 83 84 // FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² 85 func (e *gfP12) FrobeniusP2(a *gfP12) *gfP12 { 86 e.x.FrobeniusP2(&a.x) 87 e.x.MulGFP(&e.x, xiToPSquaredMinus1Over6) 88 e.y.FrobeniusP2(&a.y) 89 return e 90 } 91 92 func (e *gfP12) FrobeniusP4(a *gfP12) *gfP12 { 93 e.x.FrobeniusP4(&a.x) 94 e.x.MulGFP(&e.x, xiToPSquaredMinus1Over3) 95 e.y.FrobeniusP4(&a.y) 96 return e 97 } 98 99 func (e *gfP12) Add(a, b *gfP12) *gfP12 { 100 e.x.Add(&a.x, &b.x) 101 e.y.Add(&a.y, &b.y) 102 return e 103 } 104 105 func (e *gfP12) Sub(a, b *gfP12) *gfP12 { 106 e.x.Sub(&a.x, &b.x) 107 e.y.Sub(&a.y, &b.y) 108 return e 109 } 110 111 func (e *gfP12) Mul(a, b *gfP12) *gfP12 { 112 tx := (&gfP6{}).Mul(&a.x, &b.y) 113 t := (&gfP6{}).Mul(&b.x, &a.y) 114 tx.Add(tx, t) 115 116 ty := (&gfP6{}).Mul(&a.y, &b.y) 117 t.Mul(&a.x, &b.x).MulTau(t) 118 119 e.x.Set(tx) 120 e.y.Add(ty, t) 121 return e 122 } 123 124 func (e *gfP12) MulScalar(a *gfP12, b *gfP6) *gfP12 { 125 e.x.Mul(&e.x, b) 126 e.y.Mul(&e.y, b) 127 return e 128 } 129 130 func (c *gfP12) Exp(a *gfP12, power *big.Int) *gfP12 { 131 sum := (&gfP12{}).SetOne() 132 t := &gfP12{} 133 134 for i := power.BitLen() - 1; i >= 0; i-- { 135 t.Square(sum) 136 if power.Bit(i) != 0 { 137 sum.Mul(t, a) 138 } else { 139 sum.Set(t) 140 } 141 } 142 143 c.Set(sum) 144 return c 145 } 146 147 func (e *gfP12) Square(a *gfP12) *gfP12 { 148 // Complex squaring algorithm 149 v0 := (&gfP6{}).Mul(&a.x, &a.y) 150 151 t := (&gfP6{}).MulTau(&a.x) 152 t.Add(&a.y, t) 153 ty := (&gfP6{}).Add(&a.x, &a.y) 154 ty.Mul(ty, t).Sub(ty, v0) 155 t.MulTau(v0) 156 ty.Sub(ty, t) 157 158 e.x.Add(v0, v0) 159 e.y.Set(ty) 160 return e 161 } 162 163 func (e *gfP12) Invert(a *gfP12) *gfP12 { 164 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 165 // ftp://136.206.11.249/pub/crypto/pairings.pdf 166 t1, t2 := &gfP6{}, &gfP6{} 167 168 t1.Square(&a.x) 169 t2.Square(&a.y) 170 t1.MulTau(t1).Sub(t2, t1) 171 t2.Invert(t1) 172 173 e.x.Neg(&a.x) 174 e.y.Set(&a.y) 175 e.MulScalar(e, t2) 176 return e 177 }