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 }