def proveRctMG(pubs, inSk, outSk, outPk, index): #pubs is a matrix of ctkeys [P, C] #inSk is the keyvector of [x, mask] secret keys #outMasks is a keyvector of masks for outputs #outPk is a list of output ctkeys [P, C] #index is secret index of where you are signing (integer) #returns a list (mgsig) [ss, cc, II] where ss is keymatrix, cc is key, II is keyVector of keyimages #so we are calling MLSAG2.MLSAG_Gen from here, we need a keymatrix made from pubs #we also need a keyvector made from inSk rows = len(pubs[0]) cols = len(pubs) print("rows in mg", rows) print("cols in mg", cols) M = MLSAG2.keyMatrix(rows + 1, cols) #just a simple way to initialize a keymatrix, doesn't need to be random.. sk = MLSAG2.keyVector(rows + 1) for j in range(0, cols): M[j][rows] = MiniNero.identity() sk[rows] = MiniNero.sc_0() for i in range(0, rows): sk[i] = inSk[i].dest #get the destination part sk[rows] = MiniNero.sc_add_keys(sk[rows], inSk[i].mask) #add commitment part for j in range(0, cols): M[j][i] = pubs[j][i].dest # get the destination part M[j][rows] = MiniNero.addKeys(M[j][rows], pubs[j][i].mask) #add commitment part #next need to subtract the commitment part of all outputs.. for j in range(0, len(outSk)): sk[rows] = MiniNero.sc_sub_keys(sk[rows], outSk[j].mask) for i in range(0, len(outPk)): M[j][rows] = MiniNero.subKeys(M[j][rows], outPk[i].mask) # subtract commitment part MG = mgSig() MG.II, MG.cc, MG.ss = MLSAG2.MLSAG_Gen(M, sk, index) return MG #mgSig
def proveRange(amount): bb = d2b(amount, ATOMS) #gives binary form of bb in "digits" binary digits print("amount, amount in binary", amount, bb) ai = [None] * len(bb) Ci = [None] * len(bb) CiH = [None] * len(bb) #this is like Ci - 2^i H H2 = getH2ForCT() a = MiniNero.sc_0() ii = [None] * len(bb) indi = [None] * len(bb) for i in range(0, ATOMS): ai[i] = PaperWallet.skGen() a = MiniNero.addScalars( a, ai[i] ) #creating the total mask since you have to pass this to receiver... if bb[i] == 0: Ci[i] = MiniNero.scalarmultBase(ai[i]) if bb[i] == 1: Ci[i] = MiniNero.addKeys(MiniNero.scalarmultBase(ai[i]), H2[i]) CiH[i] = MiniNero.subKeys(Ci[i], H2[i]) A = asnlSig() A.L1, A.s2, A.s = AggregateSchnorr.GenASNL(ai, Ci, CiH, bb) R = rangeSig() R.asig = A R.Ci = Ci mask = a C = sumCi(Ci) return C, mask, R
def proveRange(amount): bb = d2b(amount, ATOMS) #gives binary form of bb in "digits" binary digits print("amount, amount in binary", amount, bb) ai = [None] * len(bb) Ci = [None] * len(bb) CiH = [None] * len(bb) #this is like Ci - 2^i H H2 = getH2ForCT() a = MiniNero.sc_0() ii = [None] * len(bb) indi = [None] * len(bb) for i in range(0, ATOMS): ai[i] = PaperWallet.skGen() a = MiniNero.addScalars(a, ai[i]) #creating the total mask since you have to pass this to receiver... if bb[i] == 0: Ci[i] = MiniNero.scalarmultBase(ai[i]) if bb[i] == 1: Ci[i] = MiniNero.addKeys(MiniNero.scalarmultBase(ai[i]), H2[i]) CiH[i] = MiniNero.subKeys(Ci[i], H2[i]) A = asnlSig() A.L1, A.s2, A.s = AggregateSchnorr.GenASNL(ai, Ci, CiH, bb) R = rangeSig() R.asig = A R.Ci = Ci mask = a C = sumCi(Ci) return C, mask, R
def genRCTSig(sk_x, sk_in, sk_out, Pk, CIn, COut, ExpIn, ExpOut, index): #sk_x is private keys of addresses (vector) #sk_in is masks of input commitments (vector) #sk_out is masks of output commitments (vector) #Pk is public key list (2d array) #CIn is input commitments (2d array) #COut is output commitments (vector) #ExpIn is exponents for the input commitments (2d array) #so each row of this is going to correspond to a column in the actual mlsag.. #ExpOut is exponents for the output commitments #index is the secret index sk = sk_x[:] sk.append( MiniNero.sc_sub_keys(MiniNero.sc_add(sk_in, ExpIn[index]), MiniNero.sc_add(sk_out, ExpOut))) CRow = [None] * len(CIn) #commitments row of public keys Cin - Cout COutSum = sumCiExp(COut, ExpOut) #Cout1*10^i_1 + Cout2 * 10^{i_2}.. tmp = MiniNero.identity() pk = [None] * (len(sk_x) + 1) #generalize later... pk[0] = Pk for i in range(0, len(CIn)): CRow[i] = MiniNero.subKeys(sumCiExp(CIn[i], ExpIn[i]), COutSum) pk[1] = CRow II, cc, ssVal = MLSAG.MLSAG_Sign(pk, sk, index) return pk, II, cc, ssVal
def verRange(Ci, ags): n = ATOMS CiH = [None] * n H2 = getH2ForCT() for i in range(0, n): CiH[i] = MiniNero.subKeys(ags.Ci[i], H2[i]) return AggregateSchnorr.VerASNL(ags.Ci, CiH, ags.asig.L1, ags.asig.s2, ags.asig.s)
def verRangeProof(Ci, L1, s2, s): n = len( Ci ) #note there will be some fixed length eventually so you can't just get the top digit CiH = [None] * n for i in range(0, n): CiH[i] = MiniNero.subKeys( Ci[i], MiniNero.scalarmultKey(getHForCT(), MiniNero.intToHex(2**i))) return ASNL.VerASNL(Ci, CiH, L1, s2, s)
def rangeProof(C_out_i, masks_i): n = len(masks_i) I_Proofs = [None] * n c0s = [None] * n ss = [None] * n C_is = [None] * n for i in range(0, n): C_i = MiniNero.addKeys(MiniNero.scalarmultBase(masks_i[i]), MiniNero.scalarmultKey(H_ct, C_out_i[i])) # masks_i * G + C_out_i * H C_i_prime = MiniNero.subKeys(C_i, H_ct) #C_i - H C_is[i] = [C_i_prime, C_i] print("generating LLWsig for range proof from Cis, masks, couts", C_is[i], masks_i[i], C_out_i[i]) I_Proofs[i], c0s[i], ss[i] = LLW_Sigs.LLW_Sig(C_is[i], masks_i[i], MiniNero.hexToInt(C_out_i[i])) #ring sig on the above, with sk masks_i return I_Proofs, c0s, ss, C_is
def ComputeReceivedAmount(senderEphemPk, receiverSK, maskedMask, maskedAmount, Ci, exponent): ss1, ss2 = ecdh.ecdhretrieve(receiverSK, senderEphemPk) mask = MiniNero.sc_sub_keys(maskedMask, ss1) CSum = sumCi(Ci) bH = MiniNero.subKeys(CSum, MiniNero.scalarmultBase(mask)) #bH = C - aG b = MiniNero.sc_sub_keys(maskedAmount, ss2) print("received amount:", 10 ** exponent * MiniNero.hexToInt(b)) H = getHForCT() bHTent = MiniNero.scalarmultKey(H, b) print(bHTent,"=?", bH) if bHTent != bH: print("wrong amount sent!") return -1 return 0
def CT_ring_sig(pk, C_in, C_out, xz, index): print("Generating Ct ring sig") n = len(pk) pk2 = [None] * 2 for i in range(0, n): pk2[i] = MiniNero.addKeys(pk[i], C_in) for j in C_out: pk2[i] = MiniNero.subKeys(pk2[i], j) print("check validity", pk2[index], MiniNero.scalarmultBase(xz)) if pk2[index] != MiniNero.scalarmultBase(xz): print("stop lying, you don't know a key") exit() I, c0, s = LLW_Sigs.LLW_Sig(pk2, xz, index) print("Ct ring sig generated") return I, c0, s, pk2
def ComputeReceivedAmount(senderEphemPk, receiverSK, maskedMask, maskedAmount, Ci, exponent): ss1, ss2 = Ecdh.ecdhRetrieve(receiverSK, senderEphemPk) mask = MiniNero.sc_sub_keys(maskedMask, ss1) CSum = sumCi(Ci) bH = MiniNero.subKeys(CSum, MiniNero.scalarmultBase(mask)) #bH = C - aG b = MiniNero.sc_sub_keys(maskedAmount, ss2) print("received amount:", 10**exponent * MiniNero.hexToInt(b)) H = getHForCT() bHTent = MiniNero.scalarmultKey(H, b) print(bHTent, "=?", bH) if bHTent != bH: print("wrong amount sent!") return -1 return 0
def genRangeProof(b, digits): bb = binary(b, digits) #gives binary form of bb in "digits" binary digits print("b, b in binary", b, bb) ai = [None] * len(bb) Ci = [None] * len(bb) CiH = [None] * len(bb) #this is like Ci - 2^i H a = MiniNero.intToHex(0) ii = [None] * len(bb) indi = [None] * len(bb) for i in range(0, len(bb)): ai[i] = PaperWallet.skGen() a = MiniNero.addScalars(a, ai[i]) #creating the total mask since you have to pass this to receiver... Ci[i] = MiniNero.addKeys(MiniNero.scalarmultBase(ai[i]), MiniNero.scalarmultKey(getHForCT(), MiniNero.intToHex(bb[i] * 2 ** i))) CiH[i] = MiniNero.subKeys(Ci[i], MiniNero.scalarmultKey(getHForCT(), MiniNero.intToHex(2 ** i))) L1, s2, s = AggregateSchnorr.GenASNL(ai, Ci, CiH, bb) return sumCi(Ci), Ci, L1, s2, s, a
def verRctMG(MG, pubs, outPk): #mg is an mgsig (list [ss, cc, II] of keymatrix ss, keyvector II and key cc] #pubs is a matrix of ctkeys [P, C] #outPk is a list of output ctkeys [P, C] for the transaction #returns true or false rows = len(pubs[0]) cols = len(pubs) M = MLSAG2.keyMatrix(rows + 1, cols) #just a simple way to initialize a keymatrix, doesn't need to be random.. for j in range(0, cols): M[j][rows] = MiniNero.identity() for i in range(0, rows): for j in range(0, cols): M[j][i] = pubs[j][i].dest # get the destination part M[j][rows] = MiniNero.addKeys(M[j][rows], pubs[j][i].mask) #add commitment part #next need to subtract the commitment part of all outputs.. for j in range(0, cols): for i in range(0, len(outPk)): M[j][rows] = MiniNero.subKeys(M[j][rows], outPk[i].mask) # subtract commitment part return MLSAG2.MLSAG_Ver(M, MG.II, MG.cc, MG.ss)
def rangeProof(C_out_i, masks_i): n = len(masks_i) I_Proofs = [None] * n c0s = [None] * n ss = [None] * n C_is = [None] * n for i in range(0, n): C_i = MiniNero.addKeys( MiniNero.scalarmultBase(masks_i[i]), MiniNero.scalarmultKey(H_ct, C_out_i[i])) # masks_i * G + C_out_i * H C_i_prime = MiniNero.subKeys(C_i, H_ct) #C_i - H C_is[i] = [C_i_prime, C_i] print("generating LLWsig for range proof from Cis, masks, couts", C_is[i], masks_i[i], C_out_i[i]) I_Proofs[i], c0s[i], ss[i] = LLW_Sigs.LLW_Sig( C_is[i], masks_i[i], MiniNero.hexToInt(C_out_i[i])) #ring sig on the above, with sk masks_i return I_Proofs, c0s, ss, C_is
def decodeRct(rv, sk, i): #inputs: #rctSig is a list [ rangesigs, MG, mixRing, ecdhInfo, outPk] #rangesigs is a list of one rangeproof for each output #MG is the mgsig [ss, cc, II] #mixRing is a ctkeyMatrix #ecdhInfo is a list of masks / amounts for each output #outPk is a vector of ctkeys (since we have computed the commitment for each amount) #sk is the secret key of the receiver #i is the index of the receiver in the rctSig (in case of multiple destinations) #outputs: #the amount received decodedTuple = ecdhDecode(rv.ecdhInfo[i], sk) mask = decodedTuple.mask amount = decodedTuple.amount C = rv.outPk[i].mask H = getHForCT() Ctmp = MiniNero.addKeys(MiniNero.scalarmultBase(mask), MiniNero.scalarmultKey(H, amount)) if (MiniNero.subKeys(C, Ctmp) != MiniNero.identity()): print("warning, amount decoded incorrectly, will be unable to spend") return MiniNero.hexToInt(amount)
def proveRctMG(pubs, inSk, outSk, outPk, index): #pubs is a matrix of ctkeys [P, C] #inSk is the keyvector of [x, mask] secret keys #outMasks is a keyvector of masks for outputs #outPk is a list of output ctkeys [P, C] #index is secret index of where you are signing (integer) #returns a list (mgsig) [ss, cc, II] where ss is keymatrix, cc is key, II is keyVector of keyimages #so we are calling MLSAG2.MLSAG_Gen from here, we need a keymatrix made from pubs #we also need a keyvector made from inSk rows = len(pubs[0]) cols = len(pubs) print("rows in mg", rows) print("cols in mg", cols) M = MLSAG2.keyMatrix( rows + 1, cols ) #just a simple way to initialize a keymatrix, doesn't need to be random.. sk = MLSAG2.keyVector(rows + 1) for j in range(0, cols): M[j][rows] = MiniNero.identity() sk[rows] = MiniNero.sc_0() for i in range(0, rows): sk[i] = inSk[i].dest #get the destination part sk[rows] = MiniNero.sc_add_keys(sk[rows], inSk[i].mask) #add commitment part for j in range(0, cols): M[j][i] = pubs[j][i].dest # get the destination part M[j][rows] = MiniNero.addKeys( M[j][rows], pubs[j][i].mask) #add commitment part #next need to subtract the commitment part of all outputs.. for j in range(0, len(outSk)): sk[rows] = MiniNero.sc_sub_keys(sk[rows], outSk[j].mask) for i in range(0, len(outPk)): M[j][rows] = MiniNero.subKeys( M[j][rows], outPk[i].mask) # subtract commitment part MG = mgSig() MG.II, MG.cc, MG.ss = MLSAG2.MLSAG_Gen(M, sk, index) return MG #mgSig
def genRangeProof(b, digits): bb = binary(b, digits) #gives binary form of bb in "digits" binary digits print("b, b in binary", b, bb) ai = [None] * len(bb) Ci = [None] * len(bb) CiH = [None] * len(bb) #this is like Ci - 2^i H a = MiniNero.intToHex(0) ii = [None] * len(bb) indi = [None] * len(bb) for i in range(0, len(bb)): ai[i] = PaperWallet.skGen() a = MiniNero.addScalars( a, ai[i] ) #creating the total mask since you have to pass this to receiver... Ci[i] = MiniNero.addKeys( MiniNero.scalarmultBase(ai[i]), MiniNero.scalarmultKey(getHForCT(), MiniNero.intToHex(bb[i] * 2**i))) CiH[i] = MiniNero.subKeys( Ci[i], MiniNero.scalarmultKey(getHForCT(), MiniNero.intToHex(2**i))) L1, s2, s = ASNL.GenASNL(ai, Ci, CiH, bb) return sumCi(Ci), Ci, L1, s2, s, a
def verRctMG(MG, pubs, outPk): #mg is an mgsig (list [ss, cc, II] of keymatrix ss, keyvector II and key cc] #pubs is a matrix of ctkeys [P, C] #outPk is a list of output ctkeys [P, C] for the transaction #returns true or false rows = len(pubs[0]) cols = len(pubs) M = MLSAG2.keyMatrix( rows + 1, cols ) #just a simple way to initialize a keymatrix, doesn't need to be random.. for j in range(0, cols): M[j][rows] = MiniNero.identity() for i in range(0, rows): for j in range(0, cols): M[j][i] = pubs[j][i].dest # get the destination part M[j][rows] = MiniNero.addKeys( M[j][rows], pubs[j][i].mask) #add commitment part #next need to subtract the commitment part of all outputs.. for j in range(0, cols): for i in range(0, len(outPk)): M[j][rows] = MiniNero.subKeys( M[j][rows], outPk[i].mask) # subtract commitment part return MLSAG2.MLSAG_Ver(M, MG.II, MG.cc, MG.ss)
def genRCTSig(sk_x, sk_in, sk_out, Pk, CIn, COut, ExpIn, ExpOut, index): #sk_x is private keys of addresses (vector) #sk_in is masks of input commitments (vector) #sk_out is masks of output commitments (vector) #Pk is public key list (2d array) #CIn is input commitments (2d array) #COut is output commitments (vector) #ExpIn is exponents for the input commitments (2d array) #so each row of this is going to correspond to a column in the actual mlsag.. #ExpOut is exponents for the output commitments #index is the secret index sk = sk_x[:] sk.append(MiniNero.sc_sub_keys(MiniNero.sc_add(sk_in, ExpIn[index]), MiniNero.sc_add(sk_out, ExpOut))) CRow = [None] * len(CIn) #commitments row of public keys Cin - Cout COutSum = sumCiExp(COut, ExpOut) #Cout1*10^i_1 + Cout2 * 10^{i_2}.. tmp = MiniNero.identity() pk = [None] * (len(sk_x) + 1) #generalize later... pk[0] = Pk for i in range(0, len(CIn)): CRow[i] = MiniNero.subKeys(sumCiExp(CIn[i], ExpIn[i]), COutSum) pk[1] = CRow II, cc, ssVal = MLSAG.MLSAG_Sign(pk, sk, index) return pk, II, cc, ssVal
b = 7000 Cib, L1b, s2b, sb, skb = RingCT.genRangeProof(7000, digits) c = 3000 Cic, L1c, s2c, sc, skc = RingCT.genRangeProof(3000, digits) print("verifying range proofs of outputs") RingCT.verRangeProof(Cib, L1b, s2b, sb) RingCT.verRangeProof(Cic, L1c, s2c, sc) x, P1 = PaperWallet.skpkGen() P2 = PaperWallet.pkGen() C2 = PaperWallet.pkGen() #some random commitment grabbed from the blockchain ind = 0 Ca = RingCT.sumCi(Cia) Cb = RingCT.sumCi(Cib) Cc = RingCT.sumCi(Cic) sk = [x, MiniNero.sc_sub_keys(ska, MiniNero.sc_add_keys(skb, skc))] pk = [[P1, P2], [MiniNero.subKeys(Ca, MiniNero.addKeys(Cb, Cc)), MiniNero.subKeys(C2, MiniNero.addKeys(Cb, Cc)) ] ] II, cc, ssVal = MLSAG.MLSAG_Sign(pk, sk, ind) print("Sig verified?", MLSAG.MLSAG_Ver(pk, II, cc, ssVal) ) print("Finding received amount corresponding to Cib") RingCT.ComputeReceivedAmount(pe, sr, MiniNero.addScalars(ss1, skb),MiniNero.addScalars(ss2, MiniNero.intToHex(b)), Cib, 9) print("Finding received amount corresponding to Cic") RingCT.ComputeReceivedAmount(pe, sr, MiniNero.addScalars(ss1, skc), MiniNero.addScalars(ss2, MiniNero.intToHex(c)), Cic, 9) if sys.argv[1] == "MLSAG": #below is example usage. Uncomment each line for testing N = 3 #cols R = 3 #rows x = [[None]*N] #just used to generate test public keys sk = [None] * R #vector of secret keys P = [[None]*N] #stores the public keys ind = 2
b = 7000 Cb, Cib, L1b, s2b, sb, skb = RingCT.genRangeProof(7000, digits) c = 3000 Cc, Cic, L1c, s2c, sc, skc = RingCT.genRangeProof(3000, digits) print("verifying range proofs of outputs") RingCT.verRangeProof(Cib, L1b, s2b, sb) RingCT.verRangeProof(Cic, L1c, s2c, sc) x, P1 = PaperWallet.skpkGen() P2 = PaperWallet.pkGen() C2 = PaperWallet.pkGen() #some random commitment grabbed from the blockchain ind = 0 Ca = RingCT.sumCi(Cia) Cb = RingCT.sumCi(Cib) Cc = RingCT.sumCi(Cic) sk = [x, MiniNero.sc_sub_keys(ska, MiniNero.sc_add_keys(skb, skc))] pk = [[P1, P2], [MiniNero.subKeys(Ca, MiniNero.addKeys(Cb, Cc)), MiniNero.subKeys(C2, MiniNero.addKeys(Cb, Cc)) ] ] II, cc, ssVal = MLSAG.MLSAG_Sign(pk, sk, ind) print("Sig verified?", MLSAG.MLSAG_Ver(pk, II, cc, ssVal) ) print("Finding received amount corresponding to Cib") RingCT.ComputeReceivedAmount(pe, sr, MiniNero.addScalars(ss1, skb),MiniNero.addScalars(ss2, MiniNero.intToHex(b)), Cib, 9) print("Finding received amount corresponding to Cic") RingCT.ComputeReceivedAmount(pe, sr, MiniNero.addScalars(ss1, skc), MiniNero.addScalars(ss2, MiniNero.intToHex(c)), Cic, 9) if sys.argv[1] == "MLSAG": #below is example usage. Uncomment each line for testing N = 3 #cols R = 3 #rows x = [[None]*N] #just used to generate test public keys sk = [None] * R #vector of secret keys P = [[None]*N] #stores the public keys ind = 2
def verRangeProof(Ci, L1, s2, s): n = len(Ci) #note there will be some fixed length eventually so you can't just get the top digit CiH = [None] * n for i in range(0, n): CiH[i] = MiniNero.subKeys(Ci[i], MiniNero.scalarmultKey(getHForCT(), MiniNero.intToHex(2 ** i))) return AggregateSchnorr.VerASNL(Ci, CiH, L1, s2, s)
Cic, L1c, s2c, sc, skc = RingCT.genRangeProof(3000, digits) print("verifying range proofs of outputs") RingCT.verRangeProof(Cib, L1b, s2b, sb) RingCT.verRangeProof(Cic, L1c, s2c, sc) x, P1 = PaperWallet.skpkGen() P2 = PaperWallet.pkGen() C2 = PaperWallet.pkGen( ) #some random commitment grabbed from the blockchain ind = 0 Ca = RingCT.sumCi(Cia) Cb = RingCT.sumCi(Cib) Cc = RingCT.sumCi(Cic) sk = [x, MiniNero.sc_sub_keys(ska, MiniNero.sc_add_keys(skb, skc))] pk = [[P1, P2], [ MiniNero.subKeys(Ca, MiniNero.addKeys(Cb, Cc)), MiniNero.subKeys(C2, MiniNero.addKeys(Cb, Cc)) ]] II, cc, ssVal = MLSAG.MLSAG_Sign(pk, sk, ind) print("Sig verified?", MLSAG.MLSAG_Ver(pk, II, cc, ssVal)) print("Finding received amount corresponding to Cib") RingCT.ComputeReceivedAmount( pe, sr, MiniNero.addScalars(ss1, skb), MiniNero.addScalars(ss2, MiniNero.intToHex(b)), Cib, 9) print("Finding received amount corresponding to Cic") RingCT.ComputeReceivedAmount( pe, sr, MiniNero.addScalars(ss1, skc), MiniNero.addScalars(ss2, MiniNero.intToHex(c)), Cic, 9) if sys.argv[1] == "MLSAG": #below is example usage. Uncomment each line for testing N = 3 #cols