github.com/hhwill/poc-eth@v0.0.0-20240218063348-3bb107c90dbf/crypto/curve25519/long10.go (about) 1 package curve25519 2 3 const p25 = 33554431 /* (1 << 25) - 1 */ 4 const p26 = 67108863 /* (1 << 26) - 1 */ 5 6 /* constants 2Gy and 1/(2Gy) */ 7 var base2y = &long10{39999547, 18689728, 59995525, 1648697, 57546132, 24010086, 19059592, 5425144, 63499247, 16420658} 8 9 var baseR2y = &long10{5744, 8160848, 4790893, 13779497, 35730846, 12541209, 49101323, 30047407, 40071253, 6226132} 10 11 type long10 [10]int64 12 13 /* Convert to internal format from little-endian byte format */ 14 func (x *long10) unpack(m []byte) { 15 x[0] = int64(m[0]&0xFF) | int64(m[1]&0xFF)<<8 | int64(m[2]&0xFF)<<16 | (int64(m[3]&0xFF)&3)<<24 16 x[1] = (int64(m[3]&0xFF)&^3)>>2 | int64(m[4]&0xFF)<<6 | int64(m[5]&0xFF)<<14 | (int64(m[6]&0xFF)&7)<<22 17 x[2] = (int64(m[6]&0xFF)&^7)>>3 | int64(m[7]&0xFF)<<5 | int64(m[8]&0xFF)<<13 | (int64(m[9]&0xFF)&31)<<21 18 x[3] = (int64(m[9]&0xFF)&^31)>>5 | int64(m[10]&0xFF)<<3 | int64(m[11]&0xFF)<<11 | (int64(m[12]&0xFF)&63)<<19 19 x[4] = (int64(m[12]&0xFF)&^63)>>6 | int64(m[13]&0xFF)<<2 | int64(m[14]&0xFF)<<10 | int64(m[15]&0xFF)<<18 20 x[5] = int64(m[16]&0xFF) | int64(m[17]&0xFF)<<8 | int64(m[18]&0xFF)<<16 | (int64(m[19]&0xFF)&1)<<24 21 x[6] = (int64(m[19]&0xFF)&^1)>>1 | int64(m[20]&0xFF)<<7 | int64(m[21]&0xFF)<<15 | (int64(m[22]&0xFF)&7)<<23 22 x[7] = (int64(m[22]&0xFF)&^7)>>3 | int64(m[23]&0xFF)<<5 | int64(m[24]&0xFF)<<13 | (int64(m[25]&0xFF)&15)<<21 23 x[8] = (int64(m[25]&0xFF)&^15)>>4 | int64(m[26]&0xFF)<<4 | int64(m[27]&0xFF)<<12 | (int64(m[28]&0xFF)&63)<<20 24 x[9] = (int64(m[28]&0xFF)&^63)>>6 | int64(m[29]&0xFF)<<2 | int64(m[30]&0xFF)<<10 | int64(m[31]&0xFF)<<18 25 } 26 27 /* Check if reduced-form input >= 2^255-19 */ 28 func (x *long10) isOverflow() bool { 29 return ((x[0] > p26-19) && ((x[1] & x[3] & x[5] & x[7] & x[9]) == p25) && ((x[2] & x[4] & x[6] & x[8]) == p26)) || (x[9] > p25) 30 } 31 32 /* Convert from internal format to little-endian byte format. The 33 * number must be in a reduced form which is output by the following ops: 34 * unpack, mul, sqr 35 * set -- if input in range 0 .. P25 36 * If you're unsure if the number is reduced, first multiply it by 1. */ 37 func (x *long10) pack(m []byte) []byte { 38 39 var ld int64 40 if x.isOverflow() { 41 ld = 1 42 } else { 43 ld = 0 44 } 45 if x[9] < 0 { 46 ld -= 1 47 } 48 ud := ld * -(p25 + 1) 49 ld *= 19 50 51 if m == nil { 52 m = make([]byte, 32) 53 } 54 t := ld + x[0] + (x[1] << 26) 55 56 m[0] = byte(t) 57 m[1] = byte(t >> 8) 58 m[2] = byte(t >> 16) 59 m[3] = byte(t >> 24) 60 t = (t >> 32) + (x[2] << 19) 61 62 m[4] = byte(t) 63 m[5] = byte(t >> 8) 64 m[6] = byte(t >> 16) 65 m[7] = byte(t >> 24) 66 t = (t >> 32) + (x[3] << 13) 67 68 m[8] = byte(t) 69 m[9] = byte(t >> 8) 70 m[10] = byte(t >> 16) 71 m[11] = byte(t >> 24) 72 t = (t >> 32) + (x[4] << 6) 73 74 m[12] = byte(t) 75 m[13] = byte(t >> 8) 76 m[14] = byte(t >> 16) 77 m[15] = byte(t >> 24) 78 t = (t >> 32) + x[5] + (x[6] << 25) 79 80 m[16] = byte(t) 81 m[17] = byte(t >> 8) 82 m[18] = byte(t >> 16) 83 m[19] = byte(t >> 24) 84 t = (t >> 32) + (x[7] << 19) 85 86 m[20] = byte(t) 87 m[21] = byte(t >> 8) 88 m[22] = byte(t >> 16) 89 m[23] = byte(t >> 24) 90 t = (t >> 32) + (x[8] << 12) 91 92 m[24] = byte(t) 93 m[25] = byte(t >> 8) 94 m[26] = byte(t >> 16) 95 m[27] = byte(t >> 24) 96 t = (t >> 32) + ((x[9] + ud) << 6) 97 98 m[28] = byte(t) 99 m[29] = byte(t >> 8) 100 m[30] = byte(t >> 16) 101 m[31] = byte(t >> 24) 102 return m 103 } 104 105 /* Copy a number */ 106 func (out *long10) cpy(in *long10) { 107 copy(out[:], in[:]) 108 } 109 110 /* Set a number to value, which must be in range -185861411 .. 185861411 */ 111 func (out *long10) set(in int) { 112 out[0] = int64(in) 113 for i := 1; i < len(out); i++ { 114 out[i] = 0 115 } 116 } 117 118 /* Add/subtract two numbers. The inputs must be in reduced form, and the 119 * output isn't, so to do another addition or subtraction on the output, 120 * first multiply it by one to reduce it. */ 121 func (xy *long10) add(x, y *long10) { 122 for i := 0; i < len(xy); i++ { 123 xy[i] = x[i] + y[i] 124 } 125 } 126 127 func (xy *long10) sub(x, y *long10) { 128 for i := 0; i < len(xy); i++ { 129 xy[i] = x[i] - y[i] 130 } 131 } 132 133 /* Multiply a number by a small integer in range -185861411 .. 185861411. 134 * The output is in reduced form, the input x need not be. x and xy may point 135 * to the same buffer. */ 136 func (xy *long10) mulSmall(x *long10, y int64) { 137 t := x[8] * y 138 xy[8] = t & ((1 << 26) - 1) 139 t = (t >> 26) + (x[9] * y) 140 xy[9] = t & ((1 << 25) - 1) 141 t = 19*(t>>25) + (x[0] * y) 142 xy[0] = t & ((1 << 26) - 1) 143 t = (t >> 26) + (x[1] * y) 144 xy[1] = t & ((1 << 25) - 1) 145 t = (t >> 25) + (x[2] * y) 146 xy[2] = t & ((1 << 26) - 1) 147 t = (t >> 26) + (x[3] * y) 148 xy[3] = t & ((1 << 25) - 1) 149 t = (t >> 25) + (x[4] * y) 150 xy[4] = t & ((1 << 26) - 1) 151 t = (t >> 26) + (x[5] * y) 152 xy[5] = t & ((1 << 25) - 1) 153 t = (t >> 25) + (x[6] * y) 154 xy[6] = t & ((1 << 26) - 1) 155 t = (t >> 26) + (x[7] * y) 156 xy[7] = t & ((1 << 25) - 1) 157 t = (t >> 25) + xy[8] 158 xy[8] = t & ((1 << 26) - 1) 159 xy[9] += t >> 26 160 } 161 162 /* Multiply two numbers. The output is in reduced form, the inputs need not 163 * be. */ 164 func (xy *long10) mul(x, y *long10) { 165 /* sahn0: 166 * Using local variables to avoid class access. 167 * This seem to improve performance a bit... 168 */ 169 t := x[0]*y[8] + x[2]*y[6] + x[4]*y[4] + x[6]*y[2] + x[8]*y[0] + 2*((x[1]*y[7])+(x[3]*y[5])+(x[5]*y[3])+(x[7]*y[1])) + 38*(x[9]*y[9]) 170 xy[8] = t & ((1 << 26) - 1) 171 t = (t >> 26) + x[0]*y[9] + x[1]*y[8] + x[2]*y[7] + x[3]*y[6] + x[4]*y[5] + x[5]*y[4] + x[6]*y[3] + x[7]*y[2] + x[8]*y[1] + x[9]*y[0] 172 xy[9] = t & ((1 << 25) - 1) 173 t = x[0]*y[0] + 19*((t>>25)+(x[2]*y[8])+(x[4]*y[6])+(x[6]*y[4])+(x[8]*y[2])) + 38*((x[1]*y[9])+(x[3]*y[7])+(x[5]*y[5])+(x[7]*y[3])+(x[9]*y[1])) 174 xy[0] = t & ((1 << 26) - 1) 175 t = (t >> 26) + x[0]*y[1] + x[1]*y[0] + 19*((x[2]*y[9])+(x[3]*y[8])+(x[4]*y[7])+(x[5]*y[6])+(x[6]*y[5])+(x[7]*y[4])+(x[8]*y[3])+(x[9]*y[2])) 176 xy[1] = t & ((1 << 25) - 1) 177 t = (t >> 25) + x[0]*y[2] + x[2]*y[0] + 19*((x[4]*y[8])+(x[6]*y[6])+(x[8]*y[4])) + 2*(x[1]*y[1]) + 38*((x[3]*y[9])+(x[5]*y[7])+(x[7]*y[5])+(x[9]*y[3])) 178 xy[2] = t & ((1 << 26) - 1) 179 t = (t >> 26) + x[0]*y[3] + x[1]*y[2] + x[2]*y[1] + x[3]*y[0] + 19*((x[4]*y[9])+(x[5]*y[8])+(x[6]*y[7])+(x[7]*y[6])+(x[8]*y[5])+(x[9]*y[4])) 180 xy[3] = t & ((1 << 25) - 1) 181 t = (t >> 25) + x[0]*y[4] + x[2]*y[2] + x[4]*y[0] + 19*((x[6]*y[8])+(x[8]*y[6])) + 2*((x[1]*y[3])+(x[3]*y[1])) + 38*((x[5]*y[9])+(x[7]*y[7])+(x[9]*y[5])) 182 xy[4] = t & ((1 << 26) - 1) 183 t = (t >> 26) + x[0]*y[5] + x[1]*y[4] + x[2]*y[3] + x[3]*y[2] + x[4]*y[1] + x[5]*y[0] + 19*((x[6]*y[9])+(x[7]*y[8])+(x[8]*y[7])+(x[9]*y[6])) 184 xy[5] = t & ((1 << 25) - 1) 185 t = (t >> 25) + x[0]*y[6] + x[2]*y[4] + x[4]*y[2] + x[6]*y[0] + 19*(x[8]*y[8]) + 2*((x[1]*y[5])+(x[3]*y[3])+(x[5]*y[1])) + 38*((x[7]*y[9])+(x[9]*y[7])) 186 xy[6] = t & ((1 << 26) - 1) 187 t = (t >> 26) + x[0]*y[7] + x[1]*y[6] + x[2]*y[5] + x[3]*y[4] + x[4]*y[3] + x[5]*y[2] + x[6]*y[1] + x[7]*y[0] + 19*((x[8]*y[9])+(x[9]*y[8])) 188 xy[7] = t & ((1 << 25) - 1) 189 t = (t >> 25) + xy[8] 190 xy[8] = t & ((1 << 26) - 1) 191 xy[9] += t >> 26 192 } 193 194 /* Square a number. Optimization of mul25519(x2, x, x) */ 195 func (x2 *long10) sqr(x *long10) { 196 t := x[4]*x[4] + 2*((x[0]*x[8])+(x[2]*x[6])) + 38*(x[9]*x[9]) + 4*((x[1]*x[7])+(x[3]*x[5])) 197 x2[8] = t & ((1 << 26) - 1) 198 t = (t >> 26) + 2*((x[0]*x[9])+(x[1]*x[8])+(x[2]*x[7])+(x[3]*x[6])+(x[4]*x[5])) 199 x2[9] = t & ((1 << 25) - 1) 200 t = 19*(t>>25) + x[0]*x[0] + 38*((x[2]*x[8])+(x[4]*x[6])+(x[5]*x[5])) + 76*((x[1]*x[9])+(x[3]*x[7])) 201 x2[0] = t & ((1 << 26) - 1) 202 t = (t >> 26) + 2*(x[0]*x[1]) + 38*((x[2]*x[9])+(x[3]*x[8])+(x[4]*x[7])+(x[5]*x[6])) 203 x2[1] = t & ((1 << 25) - 1) 204 t = (t >> 25) + 19*(x[6]*x[6]) + 2*((x[0]*x[2])+(x[1]*x[1])) + 38*(x[4]*x[8]) + 76*((x[3]*x[9])+(x[5]*x[7])) 205 x2[2] = t & ((1 << 26) - 1) 206 t = (t >> 26) + 2*((x[0]*x[3])+(x[1]*x[2])) + 38*((x[4]*x[9])+(x[5]*x[8])+(x[6]*x[7])) 207 x2[3] = t & ((1 << 25) - 1) 208 t = (t >> 25) + x[2]*x[2] + 2*(x[0]*x[4]) + 38*((x[6]*x[8])+(x[7]*x[7])) + 4*(x[1]*x[3]) + 76*(x[5]*x[9]) 209 x2[4] = t & ((1 << 26) - 1) 210 t = (t >> 26) + 2*((x[0]*x[5])+(x[1]*x[4])+(x[2]*x[3])) + 38*((x[6]*x[9])+(x[7]*x[8])) 211 x2[5] = t & ((1 << 25) - 1) 212 t = (t >> 25) + 19*(x[8]*x[8]) + 2*((x[0]*x[6])+(x[2]*x[4])+(x[3]*x[3])) + 4*(x[1]*x[5]) + 76*(x[7]*x[9]) 213 x2[6] = t & ((1 << 26) - 1) 214 t = (t >> 26) + 2*((x[0]*x[7])+(x[1]*x[6])+(x[2]*x[5])+(x[3]*x[4])) + 38*(x[8]*x[9]) 215 x2[7] = t & ((1 << 25) - 1) 216 t = (t >> 25) + x2[8] 217 x2[8] = t & ((1 << 26) - 1) 218 x2[9] += t >> 26 219 } 220 221 /* Calculates a reciprocal. The output is in reduced form, the inputs need not 222 * be. Simply calculates y = x^(p-2) so it's not too fast. */ 223 /* When sqrtAssist is true, it instead calculates y = x^((p-5)/8) */ 224 func (y *long10) recip(x *long10, sqrtAssist bool) { 225 t0 := new(long10) 226 t1 := new(long10) 227 t2 := new(long10) 228 t3 := new(long10) 229 t4 := new(long10) 230 231 /* the chain for x^(2^255-21) is straight from djb's implementation */ 232 t1.sqr(x) /* 2 == 2 * 1 */ 233 t2.sqr(t1) /* 4 == 2 * 2 */ 234 t0.sqr(t2) /* 8 == 2 * 4 */ 235 t2.mul(t0, x) /* 9 == 8 + 1 */ 236 t0.mul(t2, t1) /* 11 == 9 + 2 */ 237 t1.sqr(t0) /* 22 == 2 * 11 */ 238 t3.mul(t1, t2) /* 31 == 22 + 9 */ 239 /* == 2^5 - 2^0 */ 240 t1.sqr(t3) /* 2^6 - 2^1 */ 241 t2.sqr(t1) /* 2^7 - 2^2 */ 242 t1.sqr(t2) /* 2^8 - 2^3 */ 243 t2.sqr(t1) /* 2^9 - 2^4 */ 244 t1.sqr(t2) /* 2^10 - 2^5 */ 245 t2.mul(t1, t3) /* 2^10 - 2^0 */ 246 t1.sqr(t2) /* 2^11 - 2^1 */ 247 t3.sqr(t1) /* 2^12 - 2^2 */ 248 for i := 1; i < 5; i++ { /* t3 */ 249 t1.sqr(t3) 250 t3.sqr(t1) 251 } /* 2^20 - 2^10 */ 252 t1.mul(t3, t2) /* 2^20 - 2^0 */ 253 t3.sqr(t1) /* 2^21 - 2^1 */ 254 t4.sqr(t3) /* 2^22 - 2^2 */ 255 for i := 1; i < 10; i++ { /* t4 */ 256 t3.sqr(t4) 257 t4.sqr(t3) 258 } /* 2^40 - 2^20 */ 259 t3.mul(t4, t1) /* 2^40 - 2^0 */ 260 for i := 0; i < 5; i++ { /* t3 */ 261 t1.sqr(t3) 262 t3.sqr(t1) 263 } /* 2^50 - 2^10 */ 264 t1.mul(t3, t2) /* 2^50 - 2^0 */ 265 t2.sqr(t1) /* 2^51 - 2^1 */ 266 t3.sqr(t2) /* 2^52 - 2^2 */ 267 for i := 1; i < 25; i++ { /* t3 */ 268 t2.sqr(t3) 269 t3.sqr(t2) 270 } /* 2^100 - 2^50 */ 271 t2.mul(t3, t1) /* 2^100 - 2^0 */ 272 t3.sqr(t2) /* 2^101 - 2^1 */ 273 t4.sqr(t3) /* 2^102 - 2^2 */ 274 for i := 1; i < 50; i++ { /* t4 */ 275 t3.sqr(t4) 276 t4.sqr(t3) 277 } /* 2^200 - 2^100 */ 278 t3.mul(t4, t2) /* 2^200 - 2^0 */ 279 for i := 0; i < 25; i++ { /* t3 */ 280 t4.sqr(t3) 281 t3.sqr(t4) 282 } /* 2^250 - 2^50 */ 283 t2.mul(t3, t1) /* 2^250 - 2^0 */ 284 t1.sqr(t2) /* 2^251 - 2^1 */ 285 t2.sqr(t1) /* 2^252 - 2^2 */ 286 if sqrtAssist { 287 y.mul(x, t2) /* 2^252 - 3 */ 288 } else { 289 t1.sqr(t2) /* 2^253 - 2^3 */ 290 t2.sqr(t1) /* 2^254 - 2^4 */ 291 t1.sqr(t2) /* 2^255 - 2^5 */ 292 y.mul(t1, t0) /* 2^255 - 21 */ 293 } 294 } 295 296 /* checks if x is "negative", requires reduced input */ 297 func (x *long10) isNegative() bool { 298 tmp := int64(0) 299 if x.isOverflow() || x[9] < 0 { 300 tmp = 1 301 } 302 tmp = tmp ^ (x[0] & 1) 303 return tmp != 0 304 } 305 306 /* a square root */ 307 func (x *long10) sqrt(u *long10) { 308 v := new(long10) 309 t1 := new(long10) 310 t2 := new(long10) 311 t1.add(u, u) /* t1 = 2u */ 312 v.recip(t1, true) /* v = (2u)^((p-5)/8) */ 313 x.sqr(v) /* x = v^2 */ 314 t2.mul(t1, x) /* t2 = 2uv^2 */ 315 t2[0]-- /* t2 = 2uv^2-1 */ 316 t1.mul(v, t2) /* t1 = v(2uv^2-1) */ 317 x.mul(u, t1) /* x = uv(2uv^2-1) */ 318 } 319 320 /* t1 = ax + az 321 * t2 = ax - az */ 322 func montPrep(t1, t2, ax, az *long10) { 323 t1.add(ax, az) 324 t2.sub(ax, az) 325 } 326 327 /* A = P + Q where 328 * X(A) = ax/az 329 * X(P) = (t1+t2)/(t1-t2) 330 * X(Q) = (t3+t4)/(t3-t4) 331 * X(P-Q) = dx 332 * clobbers t1 and t2, preserves t3 and t4 */ 333 func montAdd(t1, t2, t3, t4, ax, az, dx *long10) { 334 ax.mul(t2, t3) 335 az.mul(t1, t4) 336 t1.add(ax, az) 337 t2.sub(ax, az) 338 ax.sqr(t1) 339 t1.sqr(t2) 340 az.mul(t1, dx) 341 } 342 343 /* B = 2 * Q where 344 * X(B) = bx/bz 345 * X(Q) = (t3+t4)/(t3-t4) 346 * clobbers t1 and t2, preserves t3 and t4 */ 347 func montDbl(t1, t2, t3, t4, bx, bz *long10) { 348 t1.sqr(t3) 349 t2.sqr(t4) 350 bx.mul(t1, t2) 351 t2.sub(t1, t2) 352 bz.mulSmall(t2, 121665) 353 t1.add(t1, bz) 354 bz.mul(t1, t2) 355 } 356 357 /* Y^2 = X^3 + 486662 X^2 + X 358 * t is a temporary */ 359 func (y2 *long10) xToY2(x, t *long10) { 360 if t == nil { 361 t = new(long10) 362 } 363 t.sqr(x) 364 y2.mulSmall(x, 486662) 365 t.add(t, y2) 366 t[0]++ 367 y2.mul(t, x) 368 }