github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/crypto/common_fe.go (about)

     1  package crypto
     2  
     3  // FieldElement32 represents an element of the field GF(2^255 - 19). An element
     4  // t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
     5  // t[3]+2^102 t[4]+...+2^230 t[9].  Bounds on each t[i] vary depending on
     6  // context.
     7  type FieldElement32 [10]int32
     8  
     9  // FieldElement64 represents an element of the field GF(2^255-19). An element t
    10  // represents the integer t[0] + t[1]*2^51 + t[2]*2^102 + t[3]*2^153 +
    11  // t[4]*2^204.
    12  type FieldElement64 [5]uint64
    13  
    14  func FeFromBytes32(dst *FieldElement32, src *[32]byte) {
    15  	h0 := load4(src[:])
    16  	h1 := load3(src[4:]) << 6
    17  	h2 := load3(src[7:]) << 5
    18  	h3 := load3(src[10:]) << 3
    19  	h4 := load3(src[13:]) << 2
    20  	h5 := load4(src[16:])
    21  	h6 := load3(src[20:]) << 7
    22  	h7 := load3(src[23:]) << 5
    23  	h8 := load3(src[26:]) << 4
    24  	h9 := (load3(src[29:]) & 8388607) << 2
    25  
    26  	feCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
    27  }
    28  
    29  func FeToBytes32(s *[32]byte, h *FieldElement32) {
    30  	var carry [10]int32
    31  
    32  	q := (19*h[9] + (1 << 24)) >> 25
    33  	q = (h[0] + q) >> 26
    34  	q = (h[1] + q) >> 25
    35  	q = (h[2] + q) >> 26
    36  	q = (h[3] + q) >> 25
    37  	q = (h[4] + q) >> 26
    38  	q = (h[5] + q) >> 25
    39  	q = (h[6] + q) >> 26
    40  	q = (h[7] + q) >> 25
    41  	q = (h[8] + q) >> 26
    42  	q = (h[9] + q) >> 25
    43  
    44  	// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
    45  	h[0] += 19 * q
    46  	// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
    47  
    48  	carry[0] = h[0] >> 26
    49  	h[1] += carry[0]
    50  	h[0] -= carry[0] << 26
    51  	carry[1] = h[1] >> 25
    52  	h[2] += carry[1]
    53  	h[1] -= carry[1] << 25
    54  	carry[2] = h[2] >> 26
    55  	h[3] += carry[2]
    56  	h[2] -= carry[2] << 26
    57  	carry[3] = h[3] >> 25
    58  	h[4] += carry[3]
    59  	h[3] -= carry[3] << 25
    60  	carry[4] = h[4] >> 26
    61  	h[5] += carry[4]
    62  	h[4] -= carry[4] << 26
    63  	carry[5] = h[5] >> 25
    64  	h[6] += carry[5]
    65  	h[5] -= carry[5] << 25
    66  	carry[6] = h[6] >> 26
    67  	h[7] += carry[6]
    68  	h[6] -= carry[6] << 26
    69  	carry[7] = h[7] >> 25
    70  	h[8] += carry[7]
    71  	h[7] -= carry[7] << 25
    72  	carry[8] = h[8] >> 26
    73  	h[9] += carry[8]
    74  	h[8] -= carry[8] << 26
    75  	carry[9] = h[9] >> 25
    76  	h[9] -= carry[9] << 25
    77  	// h10 = carry9
    78  
    79  	// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
    80  	// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
    81  	// evidently 2^255 h10-2^255 q = 0.
    82  	// Goal: Output h[0]+...+2^230 h[9].
    83  
    84  	s[0] = byte(h[0] >> 0)
    85  	s[1] = byte(h[0] >> 8)
    86  	s[2] = byte(h[0] >> 16)
    87  	s[3] = byte((h[0] >> 24) | (h[1] << 2))
    88  	s[4] = byte(h[1] >> 6)
    89  	s[5] = byte(h[1] >> 14)
    90  	s[6] = byte((h[1] >> 22) | (h[2] << 3))
    91  	s[7] = byte(h[2] >> 5)
    92  	s[8] = byte(h[2] >> 13)
    93  	s[9] = byte((h[2] >> 21) | (h[3] << 5))
    94  	s[10] = byte(h[3] >> 3)
    95  	s[11] = byte(h[3] >> 11)
    96  	s[12] = byte((h[3] >> 19) | (h[4] << 6))
    97  	s[13] = byte(h[4] >> 2)
    98  	s[14] = byte(h[4] >> 10)
    99  	s[15] = byte(h[4] >> 18)
   100  	s[16] = byte(h[5] >> 0)
   101  	s[17] = byte(h[5] >> 8)
   102  	s[18] = byte(h[5] >> 16)
   103  	s[19] = byte((h[5] >> 24) | (h[6] << 1))
   104  	s[20] = byte(h[6] >> 7)
   105  	s[21] = byte(h[6] >> 15)
   106  	s[22] = byte((h[6] >> 23) | (h[7] << 3))
   107  	s[23] = byte(h[7] >> 5)
   108  	s[24] = byte(h[7] >> 13)
   109  	s[25] = byte((h[7] >> 21) | (h[8] << 4))
   110  	s[26] = byte(h[8] >> 4)
   111  	s[27] = byte(h[8] >> 12)
   112  	s[28] = byte((h[8] >> 20) | (h[9] << 6))
   113  	s[29] = byte(h[9] >> 2)
   114  	s[30] = byte(h[9] >> 10)
   115  	s[31] = byte(h[9] >> 18)
   116  }
   117  
   118  func feCombine(h *FieldElement32, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
   119  	var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64
   120  
   121  	/*
   122  	  |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
   123  	    i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
   124  	  |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
   125  	    i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
   126  	*/
   127  
   128  	c0 = (h0 + (1 << 25)) >> 26
   129  	h1 += c0
   130  	h0 -= c0 << 26
   131  	c4 = (h4 + (1 << 25)) >> 26
   132  	h5 += c4
   133  	h4 -= c4 << 26
   134  	/* |h0| <= 2^25 */
   135  	/* |h4| <= 2^25 */
   136  	/* |h1| <= 1.51*2^58 */
   137  	/* |h5| <= 1.51*2^58 */
   138  
   139  	c1 = (h1 + (1 << 24)) >> 25
   140  	h2 += c1
   141  	h1 -= c1 << 25
   142  	c5 = (h5 + (1 << 24)) >> 25
   143  	h6 += c5
   144  	h5 -= c5 << 25
   145  	/* |h1| <= 2^24; from now on fits into int32 */
   146  	/* |h5| <= 2^24; from now on fits into int32 */
   147  	/* |h2| <= 1.21*2^59 */
   148  	/* |h6| <= 1.21*2^59 */
   149  
   150  	c2 = (h2 + (1 << 25)) >> 26
   151  	h3 += c2
   152  	h2 -= c2 << 26
   153  	c6 = (h6 + (1 << 25)) >> 26
   154  	h7 += c6
   155  	h6 -= c6 << 26
   156  	/* |h2| <= 2^25; from now on fits into int32 unchanged */
   157  	/* |h6| <= 2^25; from now on fits into int32 unchanged */
   158  	/* |h3| <= 1.51*2^58 */
   159  	/* |h7| <= 1.51*2^58 */
   160  
   161  	c3 = (h3 + (1 << 24)) >> 25
   162  	h4 += c3
   163  	h3 -= c3 << 25
   164  	c7 = (h7 + (1 << 24)) >> 25
   165  	h8 += c7
   166  	h7 -= c7 << 25
   167  	/* |h3| <= 2^24; from now on fits into int32 unchanged */
   168  	/* |h7| <= 2^24; from now on fits into int32 unchanged */
   169  	/* |h4| <= 1.52*2^33 */
   170  	/* |h8| <= 1.52*2^33 */
   171  
   172  	c4 = (h4 + (1 << 25)) >> 26
   173  	h5 += c4
   174  	h4 -= c4 << 26
   175  	c8 = (h8 + (1 << 25)) >> 26
   176  	h9 += c8
   177  	h8 -= c8 << 26
   178  	/* |h4| <= 2^25; from now on fits into int32 unchanged */
   179  	/* |h8| <= 2^25; from now on fits into int32 unchanged */
   180  	/* |h5| <= 1.01*2^24 */
   181  	/* |h9| <= 1.51*2^58 */
   182  
   183  	c9 = (h9 + (1 << 24)) >> 25
   184  	h0 += c9 * 19
   185  	h9 -= c9 << 25
   186  	/* |h9| <= 2^24; from now on fits into int32 unchanged */
   187  	/* |h0| <= 1.8*2^37 */
   188  
   189  	c0 = (h0 + (1 << 25)) >> 26
   190  	h1 += c0
   191  	h0 -= c0 << 26
   192  	/* |h0| <= 2^25; from now on fits into int32 unchanged */
   193  	/* |h1| <= 1.01*2^24 */
   194  
   195  	h[0] = int32(h0)
   196  	h[1] = int32(h1)
   197  	h[2] = int32(h2)
   198  	h[3] = int32(h3)
   199  	h[4] = int32(h4)
   200  	h[5] = int32(h5)
   201  	h[6] = int32(h6)
   202  	h[7] = int32(h7)
   203  	h[8] = int32(h8)
   204  	h[9] = int32(h9)
   205  }
   206  
   207  func FeFromBytes64(v *FieldElement64, x *[32]byte) {
   208  	v[0] = uint64(x[0])
   209  	v[0] |= uint64(x[1]) << 8
   210  	v[0] |= uint64(x[2]) << 16
   211  	v[0] |= uint64(x[3]) << 24
   212  	v[0] |= uint64(x[4]) << 32
   213  	v[0] |= uint64(x[5]) << 40
   214  	v[0] |= uint64(x[6]&7) << 48
   215  
   216  	v[1] = uint64(x[6]) >> 3
   217  	v[1] |= uint64(x[7]) << 5
   218  	v[1] |= uint64(x[8]) << 13
   219  	v[1] |= uint64(x[9]) << 21
   220  	v[1] |= uint64(x[10]) << 29
   221  	v[1] |= uint64(x[11]) << 37
   222  	v[1] |= uint64(x[12]&63) << 45
   223  
   224  	v[2] = uint64(x[12]) >> 6
   225  	v[2] |= uint64(x[13]) << 2
   226  	v[2] |= uint64(x[14]) << 10
   227  	v[2] |= uint64(x[15]) << 18
   228  	v[2] |= uint64(x[16]) << 26
   229  	v[2] |= uint64(x[17]) << 34
   230  	v[2] |= uint64(x[18]) << 42
   231  	v[2] |= uint64(x[19]&1) << 50
   232  
   233  	v[3] = uint64(x[19]) >> 1
   234  	v[3] |= uint64(x[20]) << 7
   235  	v[3] |= uint64(x[21]) << 15
   236  	v[3] |= uint64(x[22]) << 23
   237  	v[3] |= uint64(x[23]) << 31
   238  	v[3] |= uint64(x[24]) << 39
   239  	v[3] |= uint64(x[25]&15) << 47
   240  
   241  	v[4] = uint64(x[25]) >> 4
   242  	v[4] |= uint64(x[26]) << 4
   243  	v[4] |= uint64(x[27]) << 12
   244  	v[4] |= uint64(x[28]) << 20
   245  	v[4] |= uint64(x[29]) << 28
   246  	v[4] |= uint64(x[30]) << 36
   247  	v[4] |= uint64(x[31]&127) << 44
   248  }
   249  
   250  func FeToBytes64(r *[32]byte, v *FieldElement64) {
   251  	var t FieldElement64
   252  	feReduce64(&t, v)
   253  
   254  	r[0] = byte(t[0] & 0xff)
   255  	r[1] = byte((t[0] >> 8) & 0xff)
   256  	r[2] = byte((t[0] >> 16) & 0xff)
   257  	r[3] = byte((t[0] >> 24) & 0xff)
   258  	r[4] = byte((t[0] >> 32) & 0xff)
   259  	r[5] = byte((t[0] >> 40) & 0xff)
   260  	r[6] = byte((t[0] >> 48))
   261  
   262  	r[6] ^= byte((t[1] << 3) & 0xf8)
   263  	r[7] = byte((t[1] >> 5) & 0xff)
   264  	r[8] = byte((t[1] >> 13) & 0xff)
   265  	r[9] = byte((t[1] >> 21) & 0xff)
   266  	r[10] = byte((t[1] >> 29) & 0xff)
   267  	r[11] = byte((t[1] >> 37) & 0xff)
   268  	r[12] = byte((t[1] >> 45))
   269  
   270  	r[12] ^= byte((t[2] << 6) & 0xc0)
   271  	r[13] = byte((t[2] >> 2) & 0xff)
   272  	r[14] = byte((t[2] >> 10) & 0xff)
   273  	r[15] = byte((t[2] >> 18) & 0xff)
   274  	r[16] = byte((t[2] >> 26) & 0xff)
   275  	r[17] = byte((t[2] >> 34) & 0xff)
   276  	r[18] = byte((t[2] >> 42) & 0xff)
   277  	r[19] = byte((t[2] >> 50))
   278  
   279  	r[19] ^= byte((t[3] << 1) & 0xfe)
   280  	r[20] = byte((t[3] >> 7) & 0xff)
   281  	r[21] = byte((t[3] >> 15) & 0xff)
   282  	r[22] = byte((t[3] >> 23) & 0xff)
   283  	r[23] = byte((t[3] >> 31) & 0xff)
   284  	r[24] = byte((t[3] >> 39) & 0xff)
   285  	r[25] = byte((t[3] >> 47))
   286  
   287  	r[25] ^= byte((t[4] << 4) & 0xf0)
   288  	r[26] = byte((t[4] >> 4) & 0xff)
   289  	r[27] = byte((t[4] >> 12) & 0xff)
   290  	r[28] = byte((t[4] >> 20) & 0xff)
   291  	r[29] = byte((t[4] >> 28) & 0xff)
   292  	r[30] = byte((t[4] >> 36) & 0xff)
   293  	r[31] = byte((t[4] >> 44))
   294  }
   295  
   296  const maskLow51Bits = (1 << 51) - 1
   297  
   298  func feReduce64(t, v *FieldElement64) {
   299  	// Copy v
   300  	*t = *v
   301  
   302  	// Let v = v[0] + v[1]*2^51 + v[2]*2^102 + v[3]*2^153 + v[4]*2^204
   303  	// Reduce each limb below 2^51, propagating carries.
   304  	t[1] += t[0] >> 51
   305  	t[0] = t[0] & maskLow51Bits
   306  	t[2] += t[1] >> 51
   307  	t[1] = t[1] & maskLow51Bits
   308  	t[3] += t[2] >> 51
   309  	t[2] = t[2] & maskLow51Bits
   310  	t[4] += t[3] >> 51
   311  	t[3] = t[3] & maskLow51Bits
   312  	t[0] += (t[4] >> 51) * 19
   313  	t[4] = t[4] & maskLow51Bits
   314  
   315  	// We now have a field element t < 2^255, but need t <= 2^255-19
   316  
   317  	// Get the carry bit
   318  	c := (t[0] + 19) >> 51
   319  	c = (t[1] + c) >> 51
   320  	c = (t[2] + c) >> 51
   321  	c = (t[3] + c) >> 51
   322  	c = (t[4] + c) >> 51
   323  
   324  	t[0] += 19 * c
   325  
   326  	t[1] += t[0] >> 51
   327  	t[0] = t[0] & maskLow51Bits
   328  	t[2] += t[1] >> 51
   329  	t[1] = t[1] & maskLow51Bits
   330  	t[3] += t[2] >> 51
   331  	t[2] = t[2] & maskLow51Bits
   332  	t[4] += t[3] >> 51
   333  	t[3] = t[3] & maskLow51Bits
   334  	// no additional carry
   335  	t[4] = t[4] & maskLow51Bits
   336  }