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 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 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 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 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 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 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 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 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 GenSchnorr(hash_prefix, pub, sec, k): #modified from original algorithm to match Monero better #see the ag schnorr pdf for original alg. #Note in Monero, hash prefix is always 32 bytes.. #hash_prefix = binascii.hexlify(prefix) #k = PaperWallet.skGen() #comment for testing comm = MiniNero.scalarmultBase(k) print("comm", "hash_prefix", comm, hash_prefix) if MiniNero.scalarmultBase(sec) != pub: print"error in genSchnorr" return -1 if MiniNero.sc_check(sec) == False: print "fail in geSchnorr" return -1 c = MiniNero.sc_reduce_key(MiniNero.cn_fast_hash(hash_prefix + pub + comm)) r = MiniNero.sc_sub_keys(k, MiniNero.sc_mul_keys(c, sec)) #uncomment to test malleability c = MiniNero.sc_reduce_key(MiniNero.cn_fast_hash(hash_prefix + pub + comm)) r = MiniNero.sc_unreduce_key(MiniNero.sc_sub_keys(k, MiniNero.sc_mul_keys(c, sec))) return r, c
def GenSchnorr(hash_prefix, pub, sec, k): #modified from original algorithm to match ByteRub better #see the ag schnorr pdf for original alg. #Note in ByteRub, hash prefix is always 32 bytes.. #hash_prefix = binascii.hexlify(prefix) #k = PaperWallet.skGen() #comment for testing comm = MiniNero.scalarmultBase(k) print("comm", "hash_prefix", comm, hash_prefix) if MiniNero.scalarmultBase(sec) != pub: print "error in genSchnorr" return -1 if MiniNero.sc_check(sec) == False: print "fail in geSchnorr" return -1 c = MiniNero.sc_reduce_key(MiniNero.cn_fast_hash(hash_prefix + pub + comm)) r = MiniNero.sc_sub_keys(k, MiniNero.sc_mul_keys(c, sec)) #uncomment to test malleability c = MiniNero.sc_reduce_key(MiniNero.cn_fast_hash(hash_prefix + pub + comm)) r = MiniNero.sc_unreduce_key( MiniNero.sc_sub_keys(k, MiniNero.sc_mul_keys(c, sec))) return r, c
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 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
print("outputs") 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
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)
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