github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/crypto/ringct/ringct_simple.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 package ringct 18 19 import "fmt" 20 21 //import "sync" 22 //import "sync/atomic" 23 24 import "github.com/deroproject/derosuite/crypto" 25 26 /* this files handles the generation and verification in ringct simple */ 27 28 // NOTE the transaction must have been expanded earlier and must have a key image, mixring etc 29 // this is implementation of verRctMG from rctSigs.cpp file 30 func (r *RctSig) VerifyRCTSimple_Core() (result bool) { 31 32 result = false 33 if !(r.sigType == RCTTypeSimple || r.sigType == RCTTypeSimpleBulletproof) { 34 if DEBUGGING_MODE { 35 fmt.Printf("Signature NOT RingCT Simple or bulletproof type, verification failed\n") 36 } 37 result = false 38 return 39 } 40 41 pre_mlsag_hash := crypto.Key(Get_pre_mlsag_hash(r)) 42 43 // loop through all the inputs 44 for inputi := 0; inputi < len(r.pseudoOuts); inputi++ { 45 46 rows := 1 47 cols := len(r.MixRing[inputi]) 48 49 if cols <= 2 { 50 result = false 51 } 52 53 M := make([][]crypto.Key, cols) // lets create the double dimensional array 54 for i := 0; i < cols; i++ { 55 M[i] = make([]crypto.Key, rows+1, rows+1) 56 } 57 58 //create the matrix to mg sig 59 for i := 0; i < cols; i++ { 60 M[i][0] = r.MixRing[inputi][i].Destination 61 crypto.SubKeys(&M[i][1], &r.MixRing[inputi][i].Mask, &r.pseudoOuts[inputi]) 62 } 63 64 // do the mlsag verification 65 result = MLSAG_Ver(pre_mlsag_hash, M, &r.MlsagSigs[inputi], rows, r) 66 67 if result == false { // verification of 1 one vin failed mark, entire TX as failed 68 if DEBUGGING_MODE { 69 fmt.Printf("RCT Simple signature verification failed for input %d\n", inputi) 70 } 71 72 return 73 } 74 75 } 76 77 // we are here means everything went smoothly 78 if DEBUGGING_MODE { 79 fmt.Printf(" RCT Simple Signature successfully verified\n") 80 } 81 // result is already true so 82 83 return 84 } 85 86 // structure using which information is fed from wallet 87 // these are only used while proving ringct simple 88 type Input_info struct { 89 Amount uint64 // amount in this input 90 Key_image crypto.Hash // keyimage in this input 91 Index int // index position within ring members 92 Index_Global uint64 93 Ring_Members []uint64 // ring members already sorted absolute 94 Pubs []CtKey // public keys from ring members ( secret key from our input) 95 Sk CtKey // secret key for the input 96 } 97 98 type Output_info struct { 99 Amount uint64 // only first output is locked 100 Public_View_Key crypto.Key // taken from address 101 Public_Spend_Key crypto.Key // taken from address 102 Scalar_Key crypto.Key // used to encrypt amounts 103 // Destination crypto.Key 104 //Addr address.Address 105 } 106 107 // this will prove ringct signature 108 // message is the tx prefix hash 109 // inputs contain data of each and every input, together with the ring members and other data 110 // outputs contains the output amount and key to encode the amount 111 // fees is the fees to provide 112 // this function is equivalent to genRctSimple in rctSigs.cpp 113 func (r *RctSig) Gen_RingCT_Simple(Message crypto.Hash, inputs []Input_info, outputs []Output_info, fees uint64) { 114 115 r.sigType = RCTTypeSimple 116 r.Message = crypto.Key(Message) 117 r.txFee = fees 118 119 var sumouts, sumpouts crypto.Key 120 121 for i := range outputs { 122 var public_mask, secret_mask crypto.Key 123 r.rangeSigs = append(r.rangeSigs, *(ProveRange(&public_mask, &secret_mask, outputs[i].Amount))) 124 125 //fmt.Printf("SK %s\n", secret_mask ) 126 //fmt.Printf("PK %s\n", public_mask ) 127 crypto.ScAdd(&sumouts, &sumouts, &secret_mask) 128 // copy public mask to outpk 129 r.OutPk = append(r.OutPk, CtKey{Mask: public_mask}) 130 131 // create tuple and encrypt it, then add it the signature 132 tuple := ECdhTuple{Mask: secret_mask, Amount: *d2h(outputs[i].Amount)} 133 ecdhEncode(&tuple, outputs[i].Scalar_Key) 134 135 r.ECdhInfo = append(r.ECdhInfo, tuple) // add encrypted tuple to signature 136 } 137 138 a := make([]crypto.Key, len(inputs), len(inputs)) 139 r.pseudoOuts = make([]crypto.Key, len(inputs), len(inputs)) 140 // generate pseudoOuts so as any one can verify that sum(inputs) = sum(outputs) 141 for i := 0; i < len(inputs)-1; i++ { // we need to adjust fees in the last one 142 a[i] = crypto.SkGen() // generate random key 143 144 // Sc_0(&a[i]); // temporary for debugging puprpose, make it zero 145 146 crypto.ScReduce32(&a[i]) // reduce it for crypto purpose 147 crypto.ScAdd(&sumpouts, &a[i], &sumpouts) 148 genC(&r.pseudoOuts[i], &a[i], inputs[i].Amount) 149 } 150 151 // fmt.Printf("input len %d\n", len(inputs)) 152 crypto.ScSub(&a[len(inputs)-1], &sumouts, &sumpouts) 153 genC(&r.pseudoOuts[len(inputs)-1], &a[len(inputs)-1], inputs[len(inputs)-1].Amount) 154 155 // fmt.Printf("RCT range signature verification status %v\n", r.VerifyRctSimple()) 156 157 message := crypto.Key(Get_pre_mlsag_hash(r)) 158 for i := range inputs { 159 160 r.MlsagSigs = append(r.MlsagSigs, proveRctMGSimple(message, inputs[i].Pubs, inputs[i].Sk, a[i], r.pseudoOuts[i], inputs[i].Index)) 161 162 r.MixRing = append(r.MixRing, inputs[i].Pubs) // setup mixring for temoprary validation 163 r.MlsagSigs[i].II = make([]crypto.Key, 1, 1) 164 r.MlsagSigs[i].II[0] = crypto.Key(inputs[i].Key_image) 165 166 // fmt.Printf("rv.sigs size %d \n", len(r.MlsagSigs[i].ss)) 167 168 } 169 170 // temporary setup mixrings so tx can be verified h 171 // fmt.Printf("ringct verified %+v\n ",r.VerifyRCTSimple_Core()) 172 173 } 174 175 // this will prove ringct signature using bullet proof ranges 176 // message is the tx prefix hash 177 // inputs contain data of each and every input, together with the ring members and other data 178 // outputs contains the output amount and key to encode the amount 179 // fees is the fees to provide 180 // this function is equivalent to genRctSimple in rctSigs.cpp 181 func (r *RctSig) Gen_RingCT_Simple_BulletProof(Message crypto.Hash, inputs []Input_info, outputs []Output_info, fees uint64) { 182 183 r.sigType = RCTTypeSimpleBulletproof 184 r.Message = crypto.Key(Message) 185 r.txFee = fees 186 187 var sumouts, sumpouts crypto.Key 188 189 for i := range outputs { 190 var public_mask, secret_mask crypto.Key 191 var public_maskc, secret_maskc crypto.Key 192 193 r.BulletSigs = append(r.BulletSigs, ProveRangeBulletproof(&public_maskc, &secret_maskc, outputs[i].Amount)) 194 195 public_mask = crypto.Key(public_maskc) 196 secret_mask = crypto.Key(secret_maskc) 197 //fmt.Printf("SK %s\n", secret_mask ) 198 //fmt.Printf("PK %s\n", public_mask ) 199 crypto.ScAdd(&sumouts, &sumouts, &secret_mask) 200 // copy public mask to outpk 201 r.OutPk = append(r.OutPk, CtKey{Mask: public_mask}) 202 203 // create tuple and encrypt it, then add it the signature 204 tuple := ECdhTuple{Mask: secret_mask, Amount: *d2h(outputs[i].Amount)} 205 ecdhEncode(&tuple, outputs[i].Scalar_Key) 206 207 r.ECdhInfo = append(r.ECdhInfo, tuple) // add encrypted tuple to signature 208 } 209 210 a := make([]crypto.Key, len(inputs), len(inputs)) 211 r.pseudoOuts = make([]crypto.Key, len(inputs), len(inputs)) 212 // generate pseudoOuts so as any one can verify that sum(inputs) = sum(outputs) 213 for i := 0; i < len(inputs)-1; i++ { // we need to adjust fees in the last one 214 a[i] = crypto.SkGen() // generate random key 215 216 // Sc_0(&a[i]); // temporary for debugging puprpose, make it zero 217 218 crypto.ScReduce32(&a[i]) // reduce it for crypto purpose 219 crypto.ScAdd(&sumpouts, &a[i], &sumpouts) 220 genC(&r.pseudoOuts[i], &a[i], inputs[i].Amount) 221 } 222 223 // fmt.Printf("input len %d\n", len(inputs)) 224 crypto.ScSub(&a[len(inputs)-1], &sumouts, &sumpouts) 225 genC(&r.pseudoOuts[len(inputs)-1], &a[len(inputs)-1], inputs[len(inputs)-1].Amount) 226 227 // fmt.Printf("RCT range signature verification status %v\n", r.VerifyRctSimple()) 228 229 message := crypto.Key(Get_pre_mlsag_hash(r)) 230 for i := range inputs { 231 232 r.MlsagSigs = append(r.MlsagSigs, proveRctMGSimple(message, inputs[i].Pubs, inputs[i].Sk, a[i], r.pseudoOuts[i], inputs[i].Index)) 233 234 r.MixRing = append(r.MixRing, inputs[i].Pubs) // setup mixring for temoprary validation 235 r.MlsagSigs[i].II = make([]crypto.Key, 1, 1) 236 r.MlsagSigs[i].II[0] = crypto.Key(inputs[i].Key_image) 237 238 // fmt.Printf("rv.sigs size %d \n", len(r.MlsagSigs[i].ss)) 239 240 } 241 242 // temporary setup mixrings so tx can be verified h 243 // fmt.Printf("ringct verified %+v\n ",r.VerifyRCTSimple_Core()) 244 245 } 246 247 //Ring-ct MG sigs Simple 248 // Simple version for when we assume only 249 // post rct inputs 250 // here pubs is a vector of (P, C) length mixin 251 // inSk is x, a_in corresponding to signing index from the inputs 252 // a_out, Cout is for the output commitment 253 // index is the signing index.. 254 func proveRctMGSimple(message crypto.Key, pubs []CtKey, inSk CtKey, a crypto.Key, Cout crypto.Key, index int) (msig MlsagSig) { 255 rows := 1 256 cols := len(pubs) 257 258 if len(pubs) < 1 { 259 panic("Pubs are empty") 260 } 261 262 //tmp := make([]Key, rows+1, rows+1) 263 sk := make([]crypto.Key, rows+1, rows+1) 264 265 // next 5 lines are quite common 266 M := make([][]crypto.Key, cols) 267 for i := 0; i < (cols); i++ { 268 M[i] = make([]crypto.Key, rows+1, rows+1) 269 for j := 0; j < (rows + 1); j++ { // yes there is an extra column 270 M[i][j] = Identity // fill it with identity 271 } 272 } 273 274 for i := 0; i < (cols); i++ { 275 M[i][0] = pubs[i].Destination 276 crypto.SubKeys(&M[i][1], &pubs[i].Mask, &Cout) 277 sk[0] = inSk.Destination // these 2 lines can be moved out of loop, but original version implemented here 278 crypto.ScSub(&sk[1], &inSk.Mask, &a) 279 280 } 281 282 // call mlsag gen 283 return MLSAG_Gen(message, M, sk, index, rows) 284 }