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 }