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  }