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  }