github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/crypto/bn256/google/curve.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:36</date> 10 //</624342625985499136> 11 12 //版权所有2012 Go作者。版权所有。 13 //此源代码的使用受BSD样式的控制 14 //可以在许可文件中找到的许可证。 15 16 package bn256 17 18 import ( 19 "math/big" 20 ) 21 22 //curvePoint实现椭圆曲线y?=x?+3。积分保留在 23 //雅可比形式,有效时t=z²。G_是曲线上的一组点 24 //GF(P)。 25 type curvePoint struct { 26 x, y, z, t *big.Int 27 } 28 29 var curveB = new(big.Int).SetInt64(3) 30 31 //曲线发电机是G_的发电机。 32 var curveGen = &curvePoint{ 33 new(big.Int).SetInt64(1), 34 new(big.Int).SetInt64(2), 35 new(big.Int).SetInt64(1), 36 new(big.Int).SetInt64(1), 37 } 38 39 func newCurvePoint(pool *bnPool) *curvePoint { 40 return &curvePoint{ 41 pool.Get(), 42 pool.Get(), 43 pool.Get(), 44 pool.Get(), 45 } 46 } 47 48 func (c *curvePoint) String() string { 49 c.MakeAffine(new(bnPool)) 50 return "(" + c.x.String() + ", " + c.y.String() + ")" 51 } 52 53 func (c *curvePoint) Put(pool *bnPool) { 54 pool.Put(c.x) 55 pool.Put(c.y) 56 pool.Put(c.z) 57 pool.Put(c.t) 58 } 59 60 func (c *curvePoint) Set(a *curvePoint) { 61 c.x.Set(a.x) 62 c.y.Set(a.y) 63 c.z.Set(a.z) 64 c.t.Set(a.t) 65 } 66 67 //is on curve返回真正的iff c在曲线上,其中c必须是仿射形式。 68 func (c *curvePoint) IsOnCurve() bool { 69 yy := new(big.Int).Mul(c.y, c.y) 70 xxx := new(big.Int).Mul(c.x, c.x) 71 xxx.Mul(xxx, c.x) 72 yy.Sub(yy, xxx) 73 yy.Sub(yy, curveB) 74 if yy.Sign() < 0 || yy.Cmp(P) >= 0 { 75 yy.Mod(yy, P) 76 } 77 return yy.Sign() == 0 78 } 79 80 func (c *curvePoint) SetInfinity() { 81 c.z.SetInt64(0) 82 } 83 84 func (c *curvePoint) IsInfinity() bool { 85 return c.z.Sign() == 0 86 } 87 88 func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) { 89 if a.IsInfinity() { 90 c.Set(b) 91 return 92 } 93 if b.IsInfinity() { 94 c.Set(a) 95 return 96 } 97 98 //见http://hyper椭圆形.org/efd/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 99 100 //通过替换a=[x1:y1:z1]和b=[x2:y2:z2]来规范化点。 101 //通过[U1:S1:Z1·Z2]和[U2:S2:Z1·Z2] 102 //式中:U1=x1·z2?、S1=y1·z2?、U1=x2·z1?、S2=y2·z1?? 103 z1z1 := pool.Get().Mul(a.z, a.z) 104 z1z1.Mod(z1z1, P) 105 z2z2 := pool.Get().Mul(b.z, b.z) 106 z2z2.Mod(z2z2, P) 107 u1 := pool.Get().Mul(a.x, z2z2) 108 u1.Mod(u1, P) 109 u2 := pool.Get().Mul(b.x, z1z1) 110 u2.Mod(u2, P) 111 112 t := pool.Get().Mul(b.z, z2z2) 113 t.Mod(t, P) 114 s1 := pool.Get().Mul(a.y, t) 115 s1.Mod(s1, P) 116 117 t.Mul(a.z, z1z1) 118 t.Mod(t, P) 119 s2 := pool.Get().Mul(b.y, t) 120 s2.Mod(s2, P) 121 122 //计算x=(2h)2(s²-u1-u2) 123 //其中s=(s2-s1)/(u2-u1)是线路通过的坡度 124 //(U1、S1)和(U2、S2)。额外因子2h=2(u2-u1)来自下面的z值。 125 //这也是: 126 //4(s2-s1)2-4h 2(u1+u2)=4(s2-s1)2-4h 3-4h 2(2u1) 127 //R=J-2V 128 //以及下面的注释。 129 h := pool.Get().Sub(u2, u1) 130 xEqual := h.Sign() == 0 131 132 t.Add(h, h) 133 //I= 4H 134 i := pool.Get().Mul(t, t) 135 i.Mod(i, P) 136 //J= 4H 137 j := pool.Get().Mul(h, i) 138 j.Mod(j, P) 139 140 t.Sub(s2, s1) 141 yEqual := t.Sign() == 0 142 if xEqual && yEqual { 143 c.Double(a, pool) 144 return 145 } 146 r := pool.Get().Add(t, t) 147 148 v := pool.Get().Mul(u1, i) 149 v.Mod(v, P) 150 151 //T4=4(S2-S1) 152 t4 := pool.Get().Mul(r, r) 153 t4.Mod(t4, P) 154 t.Add(v, v) 155 t6 := pool.Get().Sub(t4, j) 156 c.x.Sub(t6, t) 157 158 //设置y=—(2h)³(s1+s*(x/4h²-u1)) 159 //这也是 160 //y=-2·s1·j-(s2-s1)(2x-2i·u1)=r(v-x)-2·s1·j 161 t.Sub(v, c.x) //T7 162 t4.Mul(s1, j) //T8 163 t4.Mod(t4, P) 164 t6.Add(t4, t4) //T9 165 t4.Mul(r, t) //T10 166 t4.Mod(t4, P) 167 c.y.Sub(t4, t6) 168 169 //设置z=2(u2-u1)·z1·z2=2h·z1·z2 170 t.Add(a.z, b.z) //T11 171 t4.Mul(t, t) //T12 172 t4.Mod(t4, P) 173 t.Sub(t4, z1z1) //T13 174 t4.Sub(t, z2z2) //T14 175 c.z.Mul(t4, h) 176 c.z.Mod(c.z, P) 177 178 pool.Put(z1z1) 179 pool.Put(z2z2) 180 pool.Put(u1) 181 pool.Put(u2) 182 pool.Put(t) 183 pool.Put(s1) 184 pool.Put(s2) 185 pool.Put(h) 186 pool.Put(i) 187 pool.Put(j) 188 pool.Put(r) 189 pool.Put(v) 190 pool.Put(t4) 191 pool.Put(t6) 192 } 193 194 func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { 195 //请参阅http://hyper椭圆形.org/efd/g1p/auto-code/shortw/jacobian-0/double/dbl-2009-l.op3 196 A := pool.Get().Mul(a.x, a.x) 197 A.Mod(A, P) 198 B := pool.Get().Mul(a.y, a.y) 199 B.Mod(B, P) 200 C_ := pool.Get().Mul(B, B) 201 C_.Mod(C_, P) 202 203 t := pool.Get().Add(a.x, B) 204 t2 := pool.Get().Mul(t, t) 205 t2.Mod(t2, P) 206 t.Sub(t2, A) 207 t2.Sub(t, C_) 208 d := pool.Get().Add(t2, t2) 209 t.Add(A, A) 210 e := pool.Get().Add(t, A) 211 f := pool.Get().Mul(e, e) 212 f.Mod(f, P) 213 214 t.Add(d, d) 215 c.x.Sub(f, t) 216 217 t.Add(C_, C_) 218 t2.Add(t, t) 219 t.Add(t2, t2) 220 c.y.Sub(d, c.x) 221 t2.Mul(e, c.y) 222 t2.Mod(t2, P) 223 c.y.Sub(t2, t) 224 225 t.Mul(a.y, a.z) 226 t.Mod(t, P) 227 c.z.Add(t, t) 228 229 pool.Put(A) 230 pool.Put(B) 231 pool.Put(C_) 232 pool.Put(t) 233 pool.Put(t2) 234 pool.Put(d) 235 pool.Put(e) 236 pool.Put(f) 237 } 238 239 func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint { 240 sum := newCurvePoint(pool) 241 sum.SetInfinity() 242 t := newCurvePoint(pool) 243 244 for i := scalar.BitLen(); i >= 0; i-- { 245 t.Double(sum, pool) 246 if scalar.Bit(i) != 0 { 247 sum.Add(t, a, pool) 248 } else { 249 sum.Set(t) 250 } 251 } 252 253 c.Set(sum) 254 sum.Put(pool) 255 t.Put(pool) 256 return c 257 } 258 259 //makeaffine将c转换为affine形式并返回c。如果c是∞,则它设置 260 //C到0:1:0。 261 func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { 262 if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { 263 return c 264 } 265 if c.IsInfinity() { 266 c.x.SetInt64(0) 267 c.y.SetInt64(1) 268 c.z.SetInt64(0) 269 c.t.SetInt64(0) 270 return c 271 } 272 zInv := pool.Get().ModInverse(c.z, P) 273 t := pool.Get().Mul(c.y, zInv) 274 t.Mod(t, P) 275 zInv2 := pool.Get().Mul(zInv, zInv) 276 zInv2.Mod(zInv2, P) 277 c.y.Mul(t, zInv2) 278 c.y.Mod(c.y, P) 279 t.Mul(c.x, zInv2) 280 t.Mod(t, P) 281 c.x.Set(t) 282 c.z.SetInt64(1) 283 c.t.SetInt64(1) 284 285 pool.Put(zInv) 286 pool.Put(t) 287 pool.Put(zInv2) 288 289 return c 290 } 291 292 func (c *curvePoint) Negative(a *curvePoint) { 293 c.x.Set(a.x) 294 c.y.Neg(a.y) 295 c.z.Set(a.z) 296 c.t.SetInt64(0) 297 } 298