github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/crypto/precompute.go (about) 1 // Copyright 2017-2018 DERO Project. All rights reserved. 2 // Use of this source code in any form is governed by RESEARCH license. 3 // license can be found in the LICENSE file. 4 // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8 5 // 6 // 7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 8 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 10 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 14 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 17 // this file includes the code related to precomputation generation 18 // and scalar multiplication 19 // each table is roughly 40 KB 20 // 32 such tables form a super table, 32 * 40KB 21 22 package crypto 23 24 import "fmt" 25 26 // table types 27 type PRECOMPUTE_TABLE [256]CachedGroupElement 28 type SUPER_PRECOMPUTE_TABLE [32]PRECOMPUTE_TABLE 29 30 type FAST_TABLE [256]PreComputedGroupElement 31 32 var x FAST_TABLE 33 34 //import "fmt" 35 //import "time" 36 //import "bytes" 37 38 // precompuate table of the form A,2A,4A,8A,16A.....2^255A 39 // se gemul8 40 // pre compute table size in bytes 256 * 4 field elemets * 5 limbs * 8 bytes 41 func GenPrecompute(table *PRECOMPUTE_TABLE, A Key) { 42 var lbi, tmp ExtendedGroupElement 43 lbi.FromBytes(&A) 44 lbi.ToCached(&table[0]) // store first entry 45 lbi.ToPreComputed(&x[0]) 46 47 var t ProjectiveGroupElement 48 var r CompletedGroupElement 49 lbi.ToProjective(&t) 50 51 var output Key 52 53 //fmt.Printf("%d %s\n",0, A) 54 55 for i := 1; i < 256; i++ { 56 t.Double(&r) 57 r.ToProjective(&t) 58 r.ToExtended(&tmp) 59 tmp.ToCached(&table[i]) 60 tmp.ToBytes(&output) 61 62 tmp.ToPreComputed(&x[i]) 63 64 //fmt.Printf("%d %s\n",i, output) 65 66 } 67 68 lbi.ToProjective(&t) 69 GeMul8(&r, &t) 70 r.ToExtended(&tmp) 71 72 tmp.ToBytes(&output) 73 74 //fmt.Printf("%d %s\n",8, output) 75 76 } 77 78 const BITS_PER_BYTE = (8) 79 80 // it finds the highest bit that is high 81 // remember the scalar is stored in little Endian 82 func GetBit(x *Key, pos uint) int { 83 if (((x)[(pos)/BITS_PER_BYTE]) & (0x1 << ((pos) % BITS_PER_BYTE))) != 0 { 84 return 1 85 } 86 return 0 87 } 88 89 // fastest Fixed based multiplicatipnn in 7.5 microseconds 90 func ScalarMultPrecompute(output *ExtendedGroupElement, scalar *Key, table *PRECOMPUTE_TABLE) { 91 output.Zero() // make it identity 92 93 // extract all bits of scalar 94 for i := uint(0); i < 256; i++ { 95 if GetBit(scalar, i) == 1 { // add precomputed table points 96 var c CompletedGroupElement 97 geAdd(&c, output, &table[i]) 98 c.ToExtended(output) 99 100 } 101 } 102 } 103 104 // this generates a very large 32*256 cached elements table roughly 1.28 MB 105 func GenSuperPrecompute(stable *SUPER_PRECOMPUTE_TABLE, ptable *PRECOMPUTE_TABLE) { 106 107 var scalar Key 108 109 for i := 0; i < 32; i++ { 110 Sc_0(&scalar) 111 for j := 0; j < 256; j++ { 112 scalar[i] = byte(j) 113 114 var result_extended ExtendedGroupElement 115 ScalarMultPrecompute(&result_extended, &scalar, ptable) 116 117 result_extended.ToCached(&stable[i][j]) 118 } 119 } 120 121 } 122 123 func ScalarMultSuperPrecompute(output *ExtendedGroupElement, scalar *Key, stable *SUPER_PRECOMPUTE_TABLE) { 124 output.Zero() // make it identity 125 126 // extract byte wise scalar and do point add 127 for i := uint(0); i < 32; i++ { 128 var c CompletedGroupElement 129 geAdd(&c, output, &stable[i][scalar[i]]) 130 c.ToExtended(output) 131 132 } 133 } 134 135 // generate tables of the form, first element is identity 136 // 0,A,2A,3A........255A 137 func MulPrecompute(r *PRECOMPUTE_TABLE, s *ExtendedGroupElement) { 138 var t CompletedGroupElement 139 var s2, u ExtendedGroupElement 140 141 var id ExtendedGroupElement 142 id.Zero() 143 id.ToCached(&r[0]) 144 s.ToCached(&r[1]) 145 s.Double(&t) 146 t.ToExtended(&s2) 147 for i := 0; i < 254; i++ { 148 geAdd(&t, &s2, &r[i]) 149 t.ToExtended(&u) 150 u.ToCached(&r[i+2]) 151 } 152 } 153 154 // this table can be used for double scalar, double base multiplication 155 // only if the bases are fixed and scalars change 156 func GenDoublePrecompute(table *PRECOMPUTE_TABLE, A Key, B Key) { 157 158 var ATABLE, BTABLE PRECOMPUTE_TABLE 159 160 var a_ex, b_ex ExtendedGroupElement 161 a_ex.FromBytes(&A) 162 b_ex.FromBytes(&B) 163 164 MulPrecompute(&ATABLE, &a_ex) 165 MulPrecompute(&BTABLE, &b_ex) 166 167 var c CompletedGroupElement 168 169 var extended_identity ExtendedGroupElement 170 extended_identity.Zero() 171 172 var output Key 173 174 //fmt.Printf("%d %s\n",0, A) 175 176 for i := 0; i < 256; i++ { 177 178 // split into 2 parts 179 apart := i & 0xf 180 bpart := (i >> 4) & 0xf 181 182 var apoint, bpoint, result ExtendedGroupElement 183 184 // extract elements from table 185 extended_identity.Zero() // extract a point 186 geAdd(&c, &extended_identity, &ATABLE[apart]) 187 c.ToExtended(&apoint) 188 189 extended_identity.Zero() // extract b point 190 geAdd(&c, &extended_identity, &BTABLE[bpart]) 191 c.ToExtended(&bpoint) 192 193 // calculate result = A+B 194 var bcached CachedGroupElement 195 var c CompletedGroupElement 196 bpoint.ToCached(&bcached) 197 geAdd(&c, &apoint, &bcached) 198 c.ToExtended(&result) 199 200 // store result to cache 201 result.ToCached(&table[i]) 202 203 apoint.ToBytes(&output) 204 //fmt.Printf("%2x %s\n",i, output) 205 206 } 207 208 //fmt.Printf("%d %s\n",256, output) 209 } 210 211 var z = fmt.Sprintf("uy") 212 213 // r = 16 * t 214 func GeMul16(r *CompletedGroupElement, t *ProjectiveGroupElement) { 215 var u ProjectiveGroupElement 216 t.Double(r) 217 r.ToProjective(&u) 218 u.Double(r) 219 r.ToProjective(&u) 220 u.Double(r) 221 r.ToProjective(&u) 222 u.Double(r) 223 } 224 225 func multprecompscalar(output *ExtendedGroupElement, s *Key, table *PRECOMPUTE_TABLE) { 226 227 var c CompletedGroupElement 228 var p ProjectiveGroupElement 229 230 var output_bytes Key 231 232 output.Zero() 233 p.Zero() 234 235 for i := uint(255); i >= 0; i-- { 236 p.Double(&c) 237 c.ToProjective(&p) 238 c.ToExtended(output) 239 240 if GetBit(s, i) == 1 { 241 geAdd(&c, output, &table[1]) 242 c.ToExtended(output) 243 } else { 244 geAdd(&c, output, &table[0]) 245 c.ToExtended(output) 246 } 247 248 output.ToProjective(&p) // for doubling 249 250 output.ToBytes(&output_bytes) 251 //fmt.Printf("%d output %s\n", i,output_bytes) 252 253 if i == 0 { 254 break 255 } 256 } 257 /* 258 p.Double(&c) 259 c.ToProjective(&p) 260 p.Double(&c) 261 c.ToProjective(&p) 262 p.Double(&c) 263 c.ToProjective(&p) 264 p.Double(&c) 265 c.ToProjective(&p) 266 p.Double(&c) 267 c.ToProjective(&p) 268 p.Double(&c) 269 c.ToProjective(&p) 270 p.Double(&c) 271 c.ToProjective(&p) 272 p.Double(&c) 273 c.ToProjective(&p) 274 275 276 c.ToExtended(output) 277 278 279 { // process high nibble first 280 //point := ((s1[i]>>4) & 0xf) //| (((s2[i]>>4) & 0xf)<<4) 281 282 //fmt.Printf("%d hpoint %d\n",i, point ) 283 geAdd(&c, output, &ATABLE[s[i]]) 284 c.ToExtended(output) 285 } 286 287 /* 288 { // process low nibble now 289 point := ((s1[i]) & 0xf) //| (((s2[i]) & 0xf)<<4) 290 fmt.Printf("%d lpoint %d\n",i, point ) 291 geAdd(&c, output, &ATABLE[point]) 292 c.ToExtended(output) 293 } 294 */ 295 /* output.ToBytes(&output_bytes) 296 297 fmt.Printf("%d output %s\n", i,output_bytes) 298 output.ToProjective(&p) // for doubling 299 */ 300 //} 301 302 } 303 304 // does output = s1*A + s2*B using precomputed tables for A and B 305 // providing scalars in wrong order will give wrong results 306 // bases are as they were provide in the order 307 // tables must have been prepared using GenDoublePrecompute 308 func DoubleScalarDoubleBaseMulPrecomputed(output *ExtendedGroupElement, s1, s2 *Key, table *PRECOMPUTE_TABLE) { 309 310 var c CompletedGroupElement 311 var p ProjectiveGroupElement 312 313 var output_bytes Key 314 _ = output_bytes 315 316 output.Zero() 317 p.Zero() 318 319 for i := 31; i >= 0; i-- { 320 321 // we are processing 4 bits at a time 322 p.Double(&c) 323 c.ToProjective(&p) 324 p.Double(&c) 325 c.ToProjective(&p) 326 p.Double(&c) 327 c.ToProjective(&p) 328 p.Double(&c) 329 //c.ToProjective(&p) 330 c.ToExtended(output) 331 332 { // process high nibble first 333 point := ((s1[i] >> 4) & 0xf) | (((s2[i] >> 4) & 0xf) << 4) 334 335 geAdd(&c, output, &table[point]) 336 //c.ToExtended(output) 337 c.ToProjective(&p) 338 } 339 340 // again 4 bits at a time 341 p.Double(&c) 342 c.ToProjective(&p) 343 p.Double(&c) 344 c.ToProjective(&p) 345 p.Double(&c) 346 c.ToProjective(&p) 347 p.Double(&c) 348 //c.ToProjective(&p) 349 c.ToExtended(output) 350 351 { // process low nibble now 352 point := ((s1[i]) & 0xf) | (((s2[i]) & 0xf) << 4) 353 //fmt.Printf("%d lpoint %d\n",i, point ) 354 geAdd(&c, output, &table[point]) 355 c.ToExtended(output) 356 } 357 //output.ToBytes(&output_bytes) 358 359 //fmt.Printf("%d output %s\n", i,output_bytes) 360 361 output.ToProjective(&p) // for doubling 362 363 } 364 365 } 366 367 // does output = s1*A + s2*B using precomputed tables for A and B 368 // providing scalars in wrong order will give wrong results 369 // bases are as they were provide in the order 370 // tables must have been prepared using GenDoublePrecompute 371 // this multiplies 64 double scalars and is used for bulletproofs 372 func DoubleScalarDoubleBaseMulPrecomputed64(output *ExtendedGroupElement, s1, s2 []Key, table []PRECOMPUTE_TABLE) { 373 374 if len(s1) != 64 || len(s2) != 64 || len(table) != 64 { 375 panic("DoubleScalarDoubleBaseMulPrecomputed64 requires 64 members") 376 } 377 var c CompletedGroupElement 378 var p ProjectiveGroupElement 379 380 var output_bytes Key 381 _ = output_bytes 382 383 output.Zero() 384 p.Zero() 385 386 for i := 31; i >= 0; i-- { 387 388 // we are processing 4 bits at a time 389 p.Double(&c) 390 c.ToProjective(&p) 391 p.Double(&c) 392 c.ToProjective(&p) 393 p.Double(&c) 394 c.ToProjective(&p) 395 p.Double(&c) 396 //c.ToProjective(&p) 397 c.ToExtended(output) 398 399 for j := 0; j < 64; j++ { // process high nibble first 400 point := ((s1[j][i] >> 4) & 0xf) | (((s2[j][i] >> 4) & 0xf) << 4) 401 if point != 0 { // skip if point is zero 402 geAdd(&c, output, &table[j][point]) 403 c.ToExtended(output) 404 } 405 406 } 407 c.ToProjective(&p) 408 409 // again 4 bits at a time 410 p.Double(&c) 411 c.ToProjective(&p) 412 p.Double(&c) 413 c.ToProjective(&p) 414 p.Double(&c) 415 c.ToProjective(&p) 416 p.Double(&c) 417 //c.ToProjective(&p) 418 c.ToExtended(output) 419 420 for j := 0; j < 64; j++ { // process low nibble now 421 point := ((s1[j][i]) & 0xf) | (((s2[j][i]) & 0xf) << 4) 422 if point != 0 { // skip if point is zero 423 //fmt.Printf("%d lpoint %d\n",i, point ) 424 geAdd(&c, output, &table[j][point]) 425 c.ToExtended(output) 426 } 427 } 428 //output.ToBytes(&output_bytes) 429 430 //fmt.Printf("%d output %s\n", i,output_bytes) 431 432 output.ToProjective(&p) // for doubling 433 434 } 435 436 }