def MLSAG_Ver(pk, I, c0, s): rows = len(pk[0]) cols = len(pk) print("verifying MG sig of dimensions ", rows, "x ", cols) c = [None] * (cols + 1) c[0] = c0 L = keyMatrix(rows, cols) R = keyMatrix(rows, cols) m = ''.join(pk[0]) for i in range(1, cols): m = m + ''.join(pk[i]) i = 0 while i < cols: L[i] = [ MiniNero.addKeys1(s[i][j], c[i], pk[i][j]) for j in range(0, rows) ] Hi = hashKeyVector(pk[i]) R[i] = [ MiniNero.addKeys2(s[i][j], Hi[j], c[i], I[j]) for j in range(0, rows) ] oldi = i i = i + 1 c[i] = MiniNero.cn_fast_hash(m + ''.join(L[oldi]) + ''.join(R[oldi])) print("L", L) print("R", R) print("c", c) return (c0 == c[cols])
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 sumCiExp(Cis, Exp): #Cis is a vector #Exp is a vector CSum = MiniNero.identity() for i in range(0, len(Cis)): CSum = MiniNero.addKeys(CSum, MiniNero.scalarmultKey(Cis[i], MiniNero.intToHex(10 ** Exp[i]))) return CSum
def MLSAG_Ver(pk, I, c0, s ): rows = len(pk) cols = len(pk[0]) print("verifying MG sig of dimensions ",rows ,"x ", cols) c= [None] * (cols + 1) c[0] = c0 L = keyMatrix(rows, cols) R = keyMatrix(rows, cols) m = ''.join(pk[0]) for i in range(1, cols): m = m + ''.join(pk[i]) i = 0 while i < cols: L[i] = [MiniNero.addKeys1(s[i][j], c[i], pk[i][j]) for j in range(0, rows)] Hi = hashKeyVector(pk[i]) R[i] = [MiniNero.addKeys2( s[i][j], Hi[j], c[i], I[j]) for j in range(0, rows)] oldi = i i = i + 1 c[i] = MiniNero.cn_fast_hash(m+''.join(L[oldi]) + ''.join(R[oldi])) print("L", L) print("R", R) print("c", c) return (c0 == c[cols])
def getHForCT(): return "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94" A = MiniNero.publicFromInt(1) H = MiniNero.hashToPoint_ct(A) Translator.hexToC(H) print(H) return H
def keyImage(x, rows): HP = keyVector(rows) KeyImage = keyVector(rows) for i in range(0, rows): HP[i] = MiniNero.hashToPoint_cn(MiniNero.scalarmultBase(x[i])) KeyImage[i] = MiniNero.scalarmultKey(HP[i], x[i]) return KeyImage
def keyImageV(x): #takes as input a keyvector, returns the keyimage-vector return [ MiniNero.scalarmultKey( MiniNero.hashToPointCN(MiniNero.scalarmultBase(xx)), xx) for xx in x ]
def importMM(wordlist): print("for testing purposes only!") sk = MiniNero.recoverSK(wordlist) print("vk", vk) print("pvk", MiniNero.publicFromSecret(vk)) key = mnemonic.mn_encode(sk) cks = MiniNero.electrumChecksum(key) print(key + " "+cks)
def ecdhDecode(masked, receiverSk): rv = ecdhTuple() #compute shared secret sharedSec1 = MiniNero.cn_fast_hash(MiniNero.scalarmultKey(masked.senderPk, receiverSk)) sharedSec2 = MiniNero.cn_fast_hash(sharedSec1) #encode rv.mask = MiniNero.sc_sub_keys(masked.mask, sharedSec1) rv.amount = MiniNero.sc_sub_keys(masked.amount, sharedSec1) return rv
def ctskpkGen(amount): sk = ctkey() pk = ctkey() sk.dest, pk.dest = PaperWallet.skpkGen() sk.mask, pk.mask = PaperWallet.skpkGen() am = MiniNero.intToHex(amount) aH = MiniNero.scalarmultKey(getHForCT(), am) pk.mask = MiniNero.addKeys(pk.mask, aH) return sk, pk
def sumCiExp(Cis, Exp): #Cis is a vector #Exp is a vector CSum = MiniNero.identity() for i in range(0, len(Cis)): CSum = MiniNero.addKeys( CSum, MiniNero.scalarmultKey(Cis[i], MiniNero.intToHex(10**Exp[i]))) return CSum
def getH2ForCT(): A = MiniNero.publicFromInt(1) HPow2 = MiniNero.hashToPoint_ct(A) two = MiniNero.intToHex(2) H2 = [None] * 64 for i in range(0, 64): Translator.hexToCComma(HPow2) H2[i] = HPow2 HPow2 = MiniNero.scalarmultKey(HPow2, two) return H2
def getH2ForCT(): A = MiniNero.publicFromInt(1) HPow2 = MiniNero.hashToPoint_ct(A) two = MiniNero.intToHex(2) H2 = [None] * ATOMS for i in range(0, ATOMS): #Translator.hexToCComma(HPow2) H2[i] = HPow2 HPow2 = MiniNero.scalarmultKey(HPow2, two) return H2
def ecdhEncode(unmasked, receiverPk): rv = ecdhTuple() #compute shared secret esk, rv.senderPk = PaperWallet.skpkGen() sharedSec1 = MiniNero.cn_fast_hash(MiniNero.scalarmultKey(receiverPk, esk)) sharedSec2 = MiniNero.cn_fast_hash(sharedSec1) #encode rv.mask = MiniNero.sc_add_keys(unmasked.mask, sharedSec1) rv.amount = MiniNero.sc_add_keys(unmasked.amount, sharedSec1) return rv
def ecdhEncode(unmasked, receiverPk): rv = ecdhTuple() #compute shared secret esk, rv.senderPk = PaperWallet.skpkGen() sharedSec1 = MiniNero.cn_fast_hash(MiniNero.scalarmultKey(receiverPk, esk)); sharedSec2 = MiniNero.cn_fast_hash(sharedSec1) #encode rv.mask = MiniNero.sc_add_keys(unmasked.mask, sharedSec1) rv.amount = MiniNero.sc_add_keys(unmasked.amount, sharedSec1) return rv
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 ecdhDecode(masked, receiverSk): rv = ecdhTuple() #compute shared secret sharedSec1 = MiniNero.cn_fast_hash( MiniNero.scalarmultKey(masked.senderPk, receiverSk)) sharedSec2 = MiniNero.cn_fast_hash(sharedSec1) #encode rv.mask = MiniNero.sc_sub_keys(masked.mask, sharedSec1) rv.amount = MiniNero.sc_sub_keys(masked.amount, sharedSec1) return rv
def MLSAG_Ver(pk, keyimage, c1, s ): rows = len(pk) cols = len(pk[0]) print("verifying MLSAG sig of dimensions ",rows ,"x ", cols) L = [[None]*cols] R = [[None]*cols] pj = ''.join(pk[0]) for i in range(1, rows): L.append([None] * cols) R.append([None] * cols) pj = pj + ''.join(pk[i]) c= [None]*(cols+1) #you do an extra one, and then check the wrap around HP = [[MiniNero.hashToPoint_cn(i) for i in pk[0]]] for j in range(1, rows): HP.append([MiniNero.hashToPoint_cn(i) for i in pk[j]]) c[0] = c1 j = 0 while j < cols: tohash = pj for i in range(0, rows): L[i][j] = MiniNero.addKeys(MiniNero.scalarmultBase(s[i][j]), MiniNero.scalarmultKey(pk[i][j], c[j])) R[i][j] = MiniNero.addKeys(MiniNero.scalarmultKey(HP[i][j], s[i][j]), MiniNero.scalarmultKey(keyimage[i], c[j])) tohash = tohash + L[i][j] + R[i][j] j = j + 1 c[j] = MiniNero.cn_fast_hash(tohash) rv = (c[0] == c[cols]) print("c", c) print("sig verifies?", rv) return rv
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 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 GenASNL(x, P1, P2, indices): #Aggregate Schnorr Non-Linkable #x, P1, P2, are key vectors here, but actually you #indices specifices which column of the given row of the key vector you sign. #the key vector with the first or second key n = len(x) print("Generating Aggregate Schnorr Non-linkable Ring Signature") L1 = [None] * n s1 = [None] * n s2 = [None] * n s = MiniNero.intToHex(0) for j in range(0, n): L1[j], s1[j], s2[j] = GenSchnorrNonLinkable(x[j], P1[j], P2[j], indices[j]) s = MiniNero.sc_add_keys(s, s1[j]) return L1, s2, s
def genRct(inSk, inPk, destinations, amounts, mixin): #inputs: #inSk is signers secret ctkeyvector #inPk is signers public ctkeyvector #destinations is a keyvector of output addresses #amounts is a list of amounts corresponding to above output addresses #mixin is an integer which is the desired mixin #outputs: #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) rv = rctSig() rv.outPk = ctkeyV( len(destinations)) rv.rangeSigs = [None] * len(destinations) outSk = ctkeyV(len(destinations)) rv.ecdhInfo = [None] * len(destinations) for i in range(0, len(destinations)): rv.ecdhInfo[i] = ecdhTuple() rv.outPk[i] = ctkey() rv.outPk[i].dest = destinations[i] rv.outPk[i].mask, outSk[i].mask, rv.rangeSigs[i] = proveRange(amounts[i]) #do ecdhinfo encode / decode rv.ecdhInfo[i].mask = outSk[i].mask rv.ecdhInfo[i].amount = MiniNero.intToHex(amounts[i]) rv.ecdhInfo[i] = ecdhEncode(rv.ecdhInfo[i], destinations[i]) rv.mixRing, index = populateFromBlockchain(inPk, mixin) rv.MG = proveRctMG(rv.mixRing, inSk, outSk, rv.outPk, index) return rv
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 genRct(inSk, inPk, destinations, amounts, mixin): #inputs: #inSk is signers secret ctkeyvector #inPk is signers public ctkeyvector #destinations is a keyvector of output addresses #amounts is a list of amounts corresponding to above output addresses #mixin is an integer which is the desired mixin #outputs: #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) rv = rctSig() rv.outPk = ctkeyV(len(destinations)) rv.rangeSigs = [None] * len(destinations) outSk = ctkeyV(len(destinations)) rv.ecdhInfo = [None] * len(destinations) for i in range(0, len(destinations)): rv.ecdhInfo[i] = ecdhTuple() rv.outPk[i] = ctkey() rv.outPk[i].dest = destinations[i] rv.outPk[i].mask, outSk[i].mask, rv.rangeSigs[i] = proveRange( amounts[i]) #do ecdhinfo encode / decode rv.ecdhInfo[i].mask = outSk[i].mask rv.ecdhInfo[i].amount = MiniNero.intToHex(amounts[i]) rv.ecdhInfo[i] = ecdhEncode(rv.ecdhInfo[i], destinations[i]) rv.mixRing, index = populateFromBlockchain(inPk, mixin) rv.MG = proveRctMG(rv.mixRing, inSk, outSk, rv.outPk, index) return rv
def VerSchnorr(hash_prefix, pub, r, c): #hash_prefix = binascii.hexlify(prefix) check1 = MiniNero.toPoint(pub) comm = MiniNero.addKeys(MiniNero.scalarmultKey(pub,c), MiniNero.scalarmultBase(r)) c2 = MiniNero.cn_fast_hash(hash_prefix + pub + comm) print(MiniNero.sc_sub_keys(c, c2) == "0000000000000000000000000000000000000000000000000000000000000000") return (MiniNero.sc_sub_keys(c, c2) == "0000000000000000000000000000000000000000000000000000000000000000")
def MLSAG_Gen(pk, xx, index ): rows = len(xx) cols = len(pk[0]) print("Generating MG sig of size ", rows, "x", cols) c= [None] * cols alpha = skvGen(rows) I = keyImageV(xx) L = keyMatrix(rows, cols) R = keyMatrix(rows, cols) s = keyMatrix(rows, cols) m = ''.join(pk[0]) for i in range(1, cols): m = m + ''.join(pk[i]) L[index] = [MiniNero.scalarmultBase(aa) for aa in alpha] #L = aG Hi = hashKeyVector(pk[index]) R[index] = [MiniNero.scalarmultKey(Hi[ii], alpha[ii]) for ii in range(0, rows)] #R = aI oldi = index i = (index + 1) % cols c[i] = MiniNero.cn_fast_hash(m+''.join(L[oldi]) + ''.join(R[oldi])) while i != index: s[i] = skvGen(rows) L[i] = [MiniNero.addKeys1(s[i][j], c[i], pk[i][j]) for j in range(0, rows)] Hi = hashKeyVector(pk[i]) R[i] = [MiniNero.addKeys2( s[i][j], Hi[j], c[i], I[j]) for j in range(0, rows)] oldi = i i = (i + 1) % cols c[i] = MiniNero.cn_fast_hash(m+''.join(L[oldi]) + ''.join(R[oldi])) print("L", L) print("R", R) s[index] = [MiniNero.sc_mulsub_keys(alpha[j], c[index], xx[j]) for j in range(0, rows)] #alpha - c * x return I, c[0], s
def VerSchnorrNonLinkable(P1, P2, L1, s1, s2): c2 = MiniNero.cn_fast_hash(L1) L2 = MiniNero.addKeys(MiniNero.scalarmultBase(s2), MiniNero.scalarmultKey(P2, c2)) c1 = MiniNero.cn_fast_hash(L2) L1p = MiniNero.addKeys(MiniNero.scalarmultBase(s1), MiniNero.scalarmultKey(P1, c1)) if L1 == L1p: print"Verified" return 0 else: print "Didn't verify" print(L1,"!=", L1p) return -1
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 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 VerSchnorrNonLinkable(P1, P2, L1, s1, s2): c2 = MiniNero.cn_fast_hash(L1) L2 = MiniNero.addKeys(MiniNero.scalarmultBase(s2), MiniNero.scalarmultKey(P2, c2)) c1 = MiniNero.cn_fast_hash(L2) L1p = MiniNero.addKeys(MiniNero.scalarmultBase(s1), MiniNero.scalarmultKey(P1, c1)) if L1 == L1p: print "Verified" return 0 else: print "Didn't verify" print(L1, "!=", L1p) return -1
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 VerSchnorr(hash_prefix, pub, r, c): #hash_prefix = binascii.hexlify(prefix) check1 = MiniNero.toPoint(pub) comm = MiniNero.addKeys(MiniNero.scalarmultKey(pub, c), MiniNero.scalarmultBase(r)) c2 = MiniNero.cn_fast_hash(hash_prefix + pub + comm) print( MiniNero.sc_sub_keys(c, c2) == "0000000000000000000000000000000000000000000000000000000000000000") return (MiniNero.sc_sub_keys(c, c2) == "0000000000000000000000000000000000000000000000000000000000000000")
def point_decompress(s): #if len(s) != 32: #raise Exception("Invalid input length for decompression") #y = int.from_bytes(s, "little") y = MiniNero.hexToInt(s) sign = y >> 255 y &= (1 << 255) - 1 x = recover_x(y, sign) if x is None: return None else: return (x, y, 1, x*y % p)
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 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 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 MLSAG_Gen(pk, xx, index): rows = len(xx) cols = len(pk) print("Generating MG sig of size ", rows, "x", cols) print("index is:", index) print("checking if I can actually sign") print(pk[index]) print([MiniNero.scalarmultBase(x) for x in xx]) c = [None] * cols alpha = skvGen(rows) I = keyImageV(xx) L = keyMatrix(rows, cols) R = keyMatrix(rows, cols) s = keyMatrix(rows, cols) m = ''.join(pk[0]) for i in range(1, cols): m = m + ''.join(pk[i]) L[index] = [MiniNero.scalarmultBase(aa) for aa in alpha] #L = aG Hi = hashKeyVector(pk[index]) R[index] = [ MiniNero.scalarmultKey(Hi[ii], alpha[ii]) for ii in range(0, rows) ] #R = aI oldi = index i = (index + 1) % cols c[i] = MiniNero.cn_fast_hash(m + ''.join(L[oldi]) + ''.join(R[oldi])) while i != index: s[i] = skvGen(rows) L[i] = [ MiniNero.addKeys1(s[i][j], c[i], pk[i][j]) for j in range(0, rows) ] Hi = hashKeyVector(pk[i]) R[i] = [ MiniNero.addKeys2(s[i][j], Hi[j], c[i], I[j]) for j in range(0, rows) ] oldi = i i = (i + 1) % cols c[i] = MiniNero.cn_fast_hash(m + ''.join(L[oldi]) + ''.join(R[oldi])) print("L", L) print("R", R) s[index] = [ MiniNero.sc_mulsub_keys(alpha[j], c[index], xx[j]) for j in range(0, rows) ] #alpha - c * x return I, c[0], s
def in_commitments(input_value, sk, masks): #for now, assume there is one input, generalized after get that working sum_masks = MiniNero.intToHex(sum([MiniNero.hexToInt(a) for a in masks])) z = MiniNero.sc_sub_keys(sk, sum_masks) # z + sum of input mask values = sk C = MiniNero.addKeys(MiniNero.scalarmultBase(sk), MiniNero.scalarmultKey( H_ct, input_value)) #input_value = sum output values return C, z #z is the sk you need to sign for this commitment
def out_commitments(values): #do this first n = len(values) values2 = [None] * n for i in range(0, n): values2[i] = [MiniNero.intToHex(j) for j in binary(MiniNero.hexToInt(values[i]))] #returns a list of commitments C_i = y_iG + value_i * H for outputs (these masks are created randomly) masks = [None] * n sumMasks = [None] * n for i in range(0, n): masks[i] = [PaperWallet.skGen() for jj in values2[i]] #binary decomposition for range proofs (could also use another base) sumMasks[i] = MiniNero.intToHex(sum([MiniNero.hexToInt(a) for a in masks[i]])) #sum is what actually goes into the ring.. C = [None] * n for i in range(0, n): C[i] = MiniNero.addKeys(MiniNero.scalarmultBase(sumMasks[i]), MiniNero.scalarmultKey(H_ct, values[i])) return C, masks, sumMasks, values2
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 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 LLW_Ver(pk, keyimage, c1, s): n= len(pk) #ok print("verifying LLW sig of length", n) L = [None]*n R = [None]*n c= [None]*(n+1) pj = ''.join(pk) HP = [MiniNero.hashToPoint_ct(i) for i in pk] c[0] = c1 j = 0 while j < n: L[j] = MiniNero.addKeys(MiniNero.scalarmultBase(s[j]), MiniNero.scalarmultKey(pk[j], c[j])) R[j] = MiniNero.addKeys(MiniNero.scalarmultKey(HP[j], s[j]), MiniNero.scalarmultKey(keyimage, c[j])) cj = j + 1 c[cj] = MiniNero.cn_fast_hash(pj + L[j] + R[j]) j = cj rv = (c[0] == c[n]) print("sig verifies complete", rv) print("c", c) print("L", L) print("R", R) return rv
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 keysBoth(): print("This is for private testing purposes only, use at your own risk!") print( "this function will generate an address that is compatible both with the main client and with MyByteRub" ) print("shen noether- mrl") print(" ") while True: print('.'), sk = skGen() #s = "3c817618dcbfed122a64e592bb441d73300da9123686224a84e0eab1f075117e"; for testing vk = MiniNero.getViewMM(sk) #note this is the sc_reduced version.. worked = 1 #uncomment below lines to make viewkey a point.. try: MiniNero.toPoint(vk) except: worked = 0 print("bad vk") if vk == MiniNero.sc_reduce_key(vk) and worked == 1: #already reduced break print("found key") print("secret spend key:", sk) print("secret view key:", vk) pk = MiniNero.publicFromSecret(sk) print("public spend key:", pk) pvk = MiniNero.publicFromSecret(vk) print("public view key:", pvk) addr = MiniNero.getAddrMM(sk) print("receiving address", addr) wl = mnemonic.mn_encode(sk) cks = MiniNero.electrumChecksum(wl) print(cks) print("mnemonic:", wl + " " + cks) return sk, vk, pk, pvk, addr, wl, cks
def moneroProofOfFile(fi): s = cnHashOfFile(fi) #s = MiniNero.sc_reduce_key(s) #if you are testing, insert #an s below this line sk = MiniNero.sc_reduce_key(s) print("secret spend key:", sk) vk = MiniNero.getView(sk) print("secret view key:", vk) pk = MiniNero.publicFromSecret(sk) print("public spend key:", pk) pvk = MiniNero.publicFromSecret(vk) print("public view key:", pvk) wl = mnemonic.mn_encode(s) cks = MiniNero.electrumChecksum(wl) print(cks) print("mnemonic:", wl + " " + cks) return MiniNero.encode_addr(MiniNero.netVersion(), pk, pvk)
def keysBoth(): print("This is for private testing purposes only, use at your own risk!") print("this function will generate an address that is compatible both with the main client and with MyMonero") print("shen noether- mrl") print(" ") while True: print('.'), sk = skGen() #s = "3c817618dcbfed122a64e592bb441d73300da9123686224a84e0eab1f075117e"; for testing vk = MiniNero.getViewMM(sk) #note this is the sc_reduced version.. worked = 1 #uncomment below lines to make viewkey a point.. try: MiniNero.toPoint(vk) except: worked =0 print("bad vk") if vk == MiniNero.sc_reduce_key(vk) and worked == 1: #already reduced break print("found key") print("secret spend key:", sk) print("secret view key:", vk) pk = MiniNero.publicFromSecret(sk) print("public spend key:", pk) pvk = MiniNero.publicFromSecret(vk) print("public view key:", pvk) addr = MiniNero.getAddrMM(sk) print("receiving address", addr) wl = mnemonic.mn_encode(sk) cks = MiniNero.electrumChecksum(wl) print(cks) print("mnemonic:", wl + " " + cks) return sk, vk, pk, pvk, addr, wl, cks
def LLW_Ver(pk, keyimage, c1, s): n = len(pk) #ok print("verifying LLW sig of length", n) L = [None] * n R = [None] * n c = [None] * (n + 1) pj = ''.join(pk) HP = [MiniNero.hashToPoint_ct(i) for i in pk] c[0] = c1 j = 0 while j < n: L[j] = MiniNero.addKeys(MiniNero.scalarmultBase(s[j]), MiniNero.scalarmultKey(pk[j], c[j])) R[j] = MiniNero.addKeys(MiniNero.scalarmultKey(HP[j], s[j]), MiniNero.scalarmultKey(keyimage, c[j])) cj = j + 1 c[cj] = MiniNero.cn_fast_hash(pj + L[j] + R[j]) j = cj rv = (c[0] == c[n]) print("sig verifies complete", rv) print("c", c) print("L", L) print("R", R) return rv
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)