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

     1  package ringct
     2  
     3  import "fmt"
     4  import "github.com/deroproject/derosuite/crypto"
     5  
     6  // this file has license pending  since it triggers a hard to find golang bug TODO add license after the golang bug is fixed
     7  /* This file implements MLSAG signatures for the transactions */
     8  
     9  // get the hash of the transaction which is used to create the mlsag later on, this hash is input to MLSAG
    10  // the hash is = hash( message + hash(basehash) + hash(pederson and borromean data))
    11  func Get_pre_mlsag_hash(sig *RctSig) crypto.Hash {
    12  
    13  	message_hash := sig.Message
    14  	base_hash := crypto.Keccak256(sig.SerializeBase())
    15  
    16  	//fmt.Printf("Message hash %s\n", message_hash)
    17  	//fmt.Printf("Base hash %s\n", base_hash)
    18  
    19  	// now join the borromean signature and extract a sig
    20  	var other_data []byte
    21  
    22  	if sig.sigType == RCTTypeSimpleBulletproof || sig.sigType == RCTTypeFullBulletproof {
    23  		for i := range sig.BulletSigs {
    24  			//for j := range sig.BulletSigs[i].V{
    25  			//	other_data= append(other_data,sig.BulletSigs[i].V[j][:]...)
    26  			//}
    27  			other_data = append(other_data, sig.BulletSigs[i].A[:]...)
    28  			other_data = append(other_data, sig.BulletSigs[i].S[:]...)
    29  			other_data = append(other_data, sig.BulletSigs[i].T1[:]...)
    30  			other_data = append(other_data, sig.BulletSigs[i].T2[:]...)
    31  			other_data = append(other_data, sig.BulletSigs[i].taux[:]...)
    32  			other_data = append(other_data, sig.BulletSigs[i].mu[:]...)
    33  			for j := range sig.BulletSigs[i].L {
    34  				other_data = append(other_data, sig.BulletSigs[i].L[j][:]...)
    35  			}
    36  			for j := range sig.BulletSigs[i].R {
    37  				other_data = append(other_data, sig.BulletSigs[i].R[j][:]...)
    38  			}
    39  			other_data = append(other_data, sig.BulletSigs[i].a[:]...)
    40  			other_data = append(other_data, sig.BulletSigs[i].b[:]...)
    41  			other_data = append(other_data, sig.BulletSigs[i].t[:]...)
    42  		}
    43  
    44  	} else if sig.sigType == RCTTypeSimple || sig.sigType == RCTTypeFull {
    45  		for i := range sig.rangeSigs {
    46  			//other_data = append(other_data,sig.rangeSigs[i].asig.s0.Serialize()...)
    47  			//other_data = append(other_data,sig.rangeSigs[i].asig.s1.Serialize()...)
    48  			//other_data = append(other_data,sig.rangeSigs[i].asig.ee[:]...)
    49  			//OR
    50  			// other_data = append(other_data, sig.rangeSigs[i].asig.Serialize()...) // serialise borrosig
    51  			//  other_data = append(other_data, sig.rangeSigs[i].ci.Serialize()...)
    52  			// OR
    53  			other_data = append(other_data, sig.rangeSigs[i].Serialize()...) // range sig serialise
    54  		}
    55  	}
    56  
    57  	other_data_hash := crypto.Keccak256(other_data)
    58  
    59  	//fmt.Printf("other  hash %s\n", other_data_hash)
    60  
    61  	// join all 3 hashes and hash them again to get the data
    62  	final_data := append(message_hash[:], base_hash[:]...)
    63  	final_data = append(final_data, other_data_hash[:]...)
    64  	final_data_hash := crypto.Keccak256(final_data)
    65  
    66  	if DEBUGGING_MODE {
    67  		fmt.Printf("final_data_hash  hash %s\n", final_data_hash)
    68  	}
    69  
    70  	return final_data_hash
    71  }
    72  
    73  //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
    74  //This is a just slghtly more efficient version than the ones described below
    75  //(will be explained in more detail in Ring Multisig paper
    76  //These are aka MG signatutes in earlier drafts of the ring ct paper
    77  // c.f. http://eprint.iacr.org/2015/1098 section 2.
    78  // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
    79  // Gen creates a signature which proves that for some column in the keymatrix "pk"
    80  //   the signer knows a secret key for each row in that column
    81  // Ver verifies that the MG sig was created correctly
    82  func MLSAG_Ver(message crypto.Key, pk [][]crypto.Key, rv *MlsagSig, dsRows int, r *RctSig) (result bool) {
    83  
    84  	defer func() { // safety so if anything wrong happens, verification fails
    85  		if r := recover(); r != nil {
    86  			result = false
    87  		}
    88  	}()
    89  
    90  	result = false
    91  	cols := len(pk)
    92  	if cols < 2 {
    93  		if DEBUGGING_MODE {
    94  			fmt.Printf("RingCT MLSAG_Ver  must have cols > 1\n")
    95  		}
    96  		result = false
    97  		return
    98  	}
    99  
   100  	rows := len(pk[0])
   101  	if rows < 1 {
   102  		if DEBUGGING_MODE {
   103  			fmt.Printf("RingCT MLSAG_Ver  must have rows > 0\n")
   104  		}
   105  		result = false
   106  		return
   107  	}
   108  
   109  	for i := 0; i < cols; i++ {
   110  		if len(pk[i]) != rows {
   111  			if DEBUGGING_MODE {
   112  				fmt.Printf("RingCT MLSAG_Ver  pk matrix not rectangular\n")
   113  			}
   114  			result = false
   115  			return
   116  		}
   117  	}
   118  
   119  	if len(rv.II) != dsRows {
   120  		if DEBUGGING_MODE {
   121  			fmt.Printf("RingCT MLSAG_Ver Bad II size\n")
   122  		}
   123  		result = false
   124  		return
   125  	}
   126  
   127  	if len(rv.ss) != cols {
   128  		if DEBUGGING_MODE {
   129  			fmt.Printf("RingCT MLSAG_Ver Bad rv.ss size   len(rv.ss) = %d cols = %d\n", len(rv.ss), cols)
   130  		}
   131  		result = false
   132  		return
   133  	}
   134  
   135  	for i := 0; i < cols; i++ {
   136  		if len(rv.ss[i]) != rows {
   137  			if DEBUGGING_MODE {
   138  				fmt.Printf("RingCT MLSAG_Ver rv.ss is not rectangular\n")
   139  			}
   140  			result = false
   141  			return
   142  		}
   143  	}
   144  
   145  	if dsRows > rows {
   146  		if DEBUGGING_MODE {
   147  			fmt.Printf("RingCT MLSAG_Ver Bad dsRows value\n")
   148  		}
   149  		result = false
   150  		return
   151  	}
   152  
   153  	for i := 0; i < len(rv.ss); i++ {
   154  		for j := 0; j < len(rv.ss[i]); j++ {
   155  			if !crypto.ScValid(&rv.ss[i][j]) {
   156  				if DEBUGGING_MODE {
   157  					fmt.Printf("RingCT MLSAG_Ver Bad ss slot\n")
   158  				}
   159  				result = false
   160  				return
   161  			}
   162  		}
   163  	}
   164  
   165  	if !crypto.ScValid(&rv.cc) {
   166  		if DEBUGGING_MODE {
   167  			fmt.Printf("RingCT MLSAG_Ver Bad r.cc slot\n")
   168  		}
   169  		result = false
   170  		return
   171  	}
   172  
   173  	//fmt.Printf("cc ver %s\n",rv.cc)
   174  
   175  	Ip := make([][8]crypto.CachedGroupElement, dsRows, dsRows) // do pre computation of key keyImage
   176  	for i := 0; i < dsRows; i++ {
   177  		key_image_point := new(crypto.ExtendedGroupElement)
   178  		key_image_point.FromBytes(&rv.II[i])
   179  		crypto.GePrecompute(&Ip[i], key_image_point)
   180  	}
   181  
   182  	ndsRows := 3 * dsRows //non Double Spendable Rows (see identity chains paper
   183  	toHash := make([]crypto.Key, 1+3*dsRows+2*(rows-dsRows), 1+3*dsRows+2*(rows-dsRows))
   184  	toHash[0] = message
   185  
   186  	// golang does NOT allow to use casts without using unsafe, so we can be slow but safe
   187  	toHash_bytes := make([]byte, 0, (1+3*dsRows+2*(rows-dsRows))*len(message))
   188  
   189  	var c crypto.Key
   190  	c_old := rv.cc
   191  	for i := 0; i < cols; i++ {
   192  		crypto.Sc_0(&c) // zero out c
   193  
   194  		var L, R, Hi crypto.Key
   195  
   196  		// first loop
   197  		for j := 0; j < dsRows; j++ {
   198  			crypto.AddKeys2(&L, &rv.ss[i][j], &c_old, &pk[i][j])
   199  			Hi = pk[i][j].HashToPoint()
   200  			crypto.AddKeys3(&R, &rv.ss[i][j], &Hi, &c_old, &Ip[j])
   201  
   202  			toHash[3*j+1] = pk[i][j]
   203  			toHash[3*j+2] = L
   204  			toHash[3*j+3] = R
   205  		}
   206  
   207  		//second loop
   208  		for j, ii := dsRows, 0; j < rows; j, ii = j+1, ii+1 {
   209  			crypto.AddKeys2(&L, &rv.ss[i][j], &c_old, &pk[i][j]) // here L is getting used again
   210  			toHash[ndsRows+2*ii+1] = pk[i][j]
   211  			toHash[ndsRows+2*ii+2] = L
   212  		}
   213  
   214  		toHash_bytes = toHash_bytes[:0] // zero out everything
   215  		for k := range toHash {
   216  			//fmt.Printf("vhash %d %s\n",k,toHash[k])
   217  			toHash_bytes = append(toHash_bytes, toHash[k][:]...)
   218  		}
   219  
   220  		c = *(crypto.HashToScalar(toHash_bytes)) // hash_to_scalar(toHash);
   221  		copy(c_old[:], c[:])                     // flipping the args here, will cause all transactions to become valid
   222  
   223  	}
   224  
   225  	if DEBUGGING_MODE {
   226  		//fmt.Printf("c     %x\n",c)
   227  		fmt.Printf("c_old %s\n", c_old)
   228  		fmt.Printf("rv.ss %s\n", rv.cc)
   229  	}
   230  
   231  	// c = c_old-rv.cc
   232  	crypto.ScSub(&c, &c_old, &rv.cc)
   233  
   234  	// if 0 checksum verified, otherwise checksum failed
   235  	result = crypto.ScIsZero(&c)
   236  
   237  	if DEBUGGING_MODE {
   238  
   239  		if result {
   240  			fmt.Printf("RingCT MLSAG_Ver Success\n")
   241  		} else {
   242  			fmt.Printf("RingCT MLSAG_Ver  verification failed\n")
   243  		}
   244  	}
   245  
   246  	return
   247  
   248  }
   249  
   250  //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
   251  //This is a just slghtly more efficient version than the ones described below
   252  //(will be explained in more detail in Ring Multisig paper
   253  //These are aka MG signatutes in earlier drafts of the ring ct paper
   254  // c.f. http://eprint.iacr.org/2015/1098 section 2.
   255  // keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
   256  // Gen creates a signature which proves that for some column in the keymatrix "pk"
   257  //   the signer knows a secret key for each row in that column
   258  // Ver verifies that the MG sig was created correctly
   259  
   260  func MLSAG_Gen(message crypto.Key, pk [][]crypto.Key, xx []crypto.Key, index int, dsRows int) (rv MlsagSig) {
   261  
   262  	result := false
   263  	_ = result
   264  	cols := len(pk)
   265  	if cols < 2 {
   266  		if DEBUGGING_MODE {
   267  			fmt.Printf("RingCT MLSAG_Gen  must have cols > 1\n")
   268  		}
   269  		result = false
   270  		return
   271  	}
   272  	if index >= cols {
   273  		panic("RingCT MLSAG_Gen Index out of range")
   274  	}
   275  	rows := len(pk[0])
   276  	if rows < 1 {
   277  		if DEBUGGING_MODE {
   278  			fmt.Printf("RingCT MLSAG_Gen  must have rows > 0\n")
   279  		}
   280  		result = false
   281  		return
   282  	}
   283  
   284  	for i := 0; i < cols; i++ {
   285  		if len(pk[i]) != rows {
   286  			if DEBUGGING_MODE {
   287  				fmt.Printf("RingCT MLSAG_Gen pk is not rectangular\n")
   288  			}
   289  			result = false
   290  			return
   291  		}
   292  	}
   293  
   294  	if len(xx) != rows {
   295  		if DEBUGGING_MODE {
   296  			fmt.Printf("RingCT MLSAG_Gen Bad xx size\n")
   297  		}
   298  		result = false
   299  		return
   300  
   301  	}
   302  
   303  	if dsRows > rows {
   304  		if DEBUGGING_MODE {
   305  			fmt.Printf("RingCT MLSAG_Gen Bad dsRows value\n")
   306  		}
   307  		result = false
   308  		return
   309  	}
   310  	var i, j int
   311  	var c, c_old, L, R, Hi crypto.Key
   312  
   313  	crypto.Sc_0(&c_old)
   314  
   315  	Ip := make([][8]crypto.CachedGroupElement, dsRows, dsRows) // do pre computation of key keyImage
   316  
   317  	rv.II = make([]crypto.Key, dsRows, dsRows)
   318  	alpha := make([]crypto.Key, rows, rows)
   319  	aG := make([]crypto.Key, rows, rows)
   320  	aHP := make([]crypto.Key, dsRows, dsRows)
   321  
   322  	//rv.ss = keyM(cols, aG); // TODO
   323  
   324  	// next 5 lines are quite common
   325  	M := make([][]crypto.Key, cols)
   326  	for i := 0; i < (cols); i++ {
   327  		M[i] = make([]crypto.Key, rows+0, rows+0)
   328  		for j := 0; j < (rows + 0); j++ { // yes there is an extra column
   329  			M[i][j] = Identity // fill it with identity
   330  		}
   331  	}
   332  	rv.ss = M
   333  
   334  	toHash := make([]crypto.Key, 1+3*dsRows+2*(rows-dsRows), 1+3*dsRows+2*(rows-dsRows))
   335  	toHash[0] = message
   336  
   337  	// golang does NOT allow to use casts without using unsafe, so we can be slow but safe
   338  	toHash_bytes := make([]byte, 0, (1+3*dsRows+2*(rows-dsRows))*len(message))
   339  
   340  	for i := 0; i < dsRows; i++ {
   341  
   342  		alpha[i] = crypto.SkGen()
   343  
   344  		// Sc_0(&alpha[i]); // make random key zero  for tesing puprpose // BUG if line is uncommented
   345  
   346  		//fmt.Printf("alpha[i] %s\n",alpha[i])
   347  		// ScReduce32(&alpha[i]) // reduce it
   348  
   349  		aG[i] = crypto.ScalarmultBase(alpha[i]) // *(alpha[i].PubKey()) //need to save alphas for later..
   350  		//skpkGen(alpha[i], aG[i]);
   351  		// Hi = hashToPoint(pk[index][i]);
   352  		Hi = pk[index][i].HashToPoint()
   353  		//aHP[i] = scalarmultKey(Hi, alpha[i]);
   354  		aHP[i] = *crypto.ScalarMultKey(&Hi, &alpha[i])
   355  		toHash[3*i+1] = pk[index][i]
   356  		toHash[3*i+2] = aG[i]
   357  		toHash[3*i+3] = aHP[i]
   358  		rv.II[i] = *crypto.ScalarMultKey(&Hi, &xx[i])
   359  		//precomp(Ip[i].k, rv.II[i]);
   360  		//fmt.Printf("secret key %s\n", xx[i])
   361  
   362  		key_image_point := new(crypto.ExtendedGroupElement)
   363  		key_image_point.FromBytes(&rv.II[i])
   364  		crypto.GePrecompute(&Ip[i], key_image_point)
   365  
   366  	}
   367  
   368  	ndsRows := 3 * dsRows //non Double Spendable Rows (see identity chains paper)
   369  	for i, ii := dsRows, 0; i < rows; i, ii = i+1, ii+1 {
   370  		//skpkGen(alpha[i], aG[i]); //need to save alphas for later..
   371  		alpha[i] = crypto.SkGen()
   372  
   373  		//Sc_0(&alpha[i]); // make random key zero  for tesing puprpose // BUG if line is uncommented
   374  		//ScReduce32(&alpha[i]) // reduce it
   375  
   376  		//aG[i] = *(alpha[i].PubKey()) //need to save alphas for later..
   377  		aG[i] = *(alpha[i].PublicKey())
   378  
   379  		toHash[ndsRows+2*ii+1] = pk[index][i]
   380  		toHash[ndsRows+2*ii+2] = aG[i]
   381  	}
   382  
   383  	toHash_bytes = toHash_bytes[:0] // zero out everything
   384  	for k := range toHash {
   385  		//fmt.Printf("gen hash %d %s\n",k,toHash[k])
   386  		toHash_bytes = append(toHash_bytes, toHash[k][:]...)
   387  	}
   388  
   389  	//c_old = hash_to_scalar(toHash);
   390  	c_old = *(crypto.HashToScalar(toHash_bytes)) // hash_to_scalar(toHash);
   391  
   392  	i = (index + 1) % cols
   393  
   394  	// fmt.Printf("hash to scalar calculated %s  index = %d\n", c_old,i)
   395  
   396  	if i == 0 {
   397  		rv.cc = c_old
   398  	}
   399  	for i != index {
   400  
   401  		//rv.ss[i] = skvGen(rows);
   402  		for j := 0; j < rows; j++ {
   403  			rv.ss[i][j] = crypto.SkGen()
   404  
   405  			//  Sc_0(&rv.ss[i][j]); // make random key zero  for tesing puprpose // BUG if line is uncommented
   406  			//ScReduce32(&rv.ss[i][j]) // reduce it
   407  
   408  		}
   409  		crypto.Sc_0(&c)
   410  
   411  		for j := 0; j < dsRows; j++ {
   412  			crypto.AddKeys2(&L, &rv.ss[i][j], &c_old, &pk[i][j])
   413  			Hi = pk[i][j].HashToPoint()
   414  			crypto.AddKeys3(&R, &rv.ss[i][j], &Hi, &c_old, &Ip[j])
   415  			/*fmt.Printf("R = %s\n",R)
   416  			fmt.Printf("rv.ss[i][j] = %s\n",rv.ss[i][j])
   417  			fmt.Printf("Hi = %s\n",Hi)
   418  			fmt.Printf("c_old = %s\n",c_old)*/
   419  
   420  			toHash[3*j+1] = pk[i][j]
   421  			toHash[3*j+2] = L
   422  			toHash[3*j+3] = R
   423  		}
   424  
   425  		//second loop
   426  		for j, ii := dsRows, 0; j < rows; j, ii = j+1, ii+1 {
   427  			crypto.AddKeys2(&L, &rv.ss[i][j], &c_old, &pk[i][j]) // here L is getting used again
   428  			toHash[ndsRows+2*ii+1] = pk[i][j]
   429  			toHash[ndsRows+2*ii+2] = L
   430  		}
   431  
   432  		toHash_bytes = toHash_bytes[:0] // zero out everything
   433  		for k := range toHash {
   434  			//fmt.Printf("gen hash cc index %d hashindex %d %s\n",i,k,toHash[k])
   435  			toHash_bytes = append(toHash_bytes, toHash[k][:]...)
   436  		}
   437  
   438  		c = *(crypto.HashToScalar(toHash_bytes)) // hash_to_scalar(toHash);
   439  
   440  		copy(c_old[:], c[:])
   441  
   442  		i = (i + 1) % cols
   443  
   444  		//fmt.Printf("cc index %d %s\n", i, c)
   445  
   446  		if i == 0 {
   447  			rv.cc = c_old
   448  		}
   449  	}
   450  	for j = 0; j < rows; j++ {
   451  		crypto.ScMulSub(&rv.ss[index][j], &c, &xx[j], &alpha[j])
   452  	}
   453  
   454  	//fmt.Printf("cc gen %s\n", rv.cc)
   455  	return rv
   456  }