Added MiniNero and RingCT code

This commit is contained in:
shnoe 2016-02-05 13:20:44 -07:00
parent d5b8d275ae
commit 55c92de3bc
64 changed files with 22162 additions and 0 deletions

View file

@ -0,0 +1,113 @@
#see the aggregate schnorr pdf contained in this repository for an explanation.
import MiniNero
import MLSAG
import LLW_Sigs
import PaperWallet
import Crypto.Random.random as rand
import binascii
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
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 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 GenSchnorrNonLinkable(x, P1, P2, index):
if index == 0:
a = PaperWallet.skGen()
L1 = MiniNero.scalarmultBase(a)
s2 = PaperWallet.skGen()
c2 = MiniNero.cn_fast_hash(L1)
L2 = MiniNero.addKeys(MiniNero.scalarmultBase(s2), MiniNero.scalarmultKey(P2, c2))
c1 = MiniNero.cn_fast_hash(L2)
s1 = MiniNero.sc_mulsub_keys(a, x, c1)
if index == 1:
a = PaperWallet.skGen()
L2 = MiniNero.scalarmultBase(a)
s1 = PaperWallet.skGen()
c1 = MiniNero.cn_fast_hash(L2)
L1 = MiniNero.addKeys(MiniNero.scalarmultBase(s1), MiniNero.scalarmultKey(P1, c1))
c2 = MiniNero.cn_fast_hash(L1)
s2 = MiniNero.sc_mulsub_keys(a, x, c2)
return L1, s1, s2,
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 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 VerASNL(P1, P2, L1, s2, s):
#Aggregate Schnorr Non-Linkable
print("Verifying Aggregate Schnorr Non-linkable Ring Signature")
n = len(P1)
LHS = MiniNero.scalarmultBase(MiniNero.intToHex(0))
RHS = MiniNero.scalarmultBase(s)
for j in range(0, n):
c2 = MiniNero.cn_fast_hash(L1[j])
L2 = MiniNero.addKeys(MiniNero.scalarmultBase(s2[j]), MiniNero.scalarmultKey(P2[j], c2))
LHS = MiniNero.addKeys(LHS, L1[j])
c1 = MiniNero.cn_fast_hash(L2)
RHS = MiniNero.addKeys(RHS, MiniNero.scalarmultKey(P1[j], c1))
if LHS == RHS:
print"Verified"
return 0
else:
print "Didn't verify"
print(LHS,"!=", RHS)
return -1

View file

@ -0,0 +1,5 @@
9
0
('checksum', '7$Z:')
1B2yLX66Q3K49NJnNF9h6Yv4aB4oUxbPC5
https://blockchain.info/address/1B2yLX66Q3K49NJnNF9h6Yv4aB4oUxbPC5

Binary file not shown.

View file

@ -0,0 +1,6 @@
592
0
(0, 'Yb\x02\xaao\xfca\xd8%\t\x10\xc1M\xbfY\x1b+\xf21F', 'here')
('checksum', '\xad\x80?[')
199cYxSJyKmkZFET9gtm3WzDHu7MpwHGTU
https://blockchain.info/address/199cYxSJyKmkZFET9gtm3WzDHu7MpwHGTU

View file

@ -0,0 +1,52 @@
#monero determinstic vk wallet test code, shen noether mrl
#use at your own risk
import Crypto.Random.random as rand
import MiniNero
import mnemonic
def deterministicVK():
while True:
print('.'),
tmp = MiniNero.intToHex(rand.getrandbits(64 * 8)) # 8 bits to a byte ...
sk = MiniNero.sc_reduce_key(MiniNero.cn_fast_hash(tmp))
#s = "3c817618dcbfed122a64e592bb441d73300da9123686224a84e0eab1f075117e"; for testing
#sk = MiniNero.sc_reduce_key(s)
vk = MiniNero.getViewMM(sk) #note this is the sc_reduced version..
worked = 1
try:
MiniNero.toPoint(vk)
except:
worked =0
print("bad vk")
if vk == MiniNero.sc_reduce_key(vk) and worked == 1: #already reduced + vk on curve
break
print("found keys")
print("secret spend key:", sk)
print("secret view key:", vk)
vk2 = MiniNero.cn_fast_hash(MiniNero.scalarmultKey(vk, 2))
print("secret view key2:", vk2)
vk3 = MiniNero.cn_fast_hash(MiniNero.scalarmultKey(vk, 3))
print("secret view key3:", vk3)
pk = MiniNero.publicFromSecret(sk)
print("public spend key:", pk)
pvk = MiniNero.publicFromSecret(vk)
print("public view key:", pvk)
pvk2 = MiniNero.publicFromSecret(vk2)
print("public view key2:", pvk2)
pvk3 = MiniNero.publicFromSecret(vk3)
print("public view key3:", pvk3)
addr = MiniNero.getAddrMM(sk)
print("in future this will get all addresses")
print("receiving address", addr)
wl = mnemonic.mn_encode(s)
cks = MiniNero.electrumChecksum(wl)
print(cks)
print("mnemonic:", wl + " " + cks)
deterministicVK()

View file

@ -0,0 +1,17 @@
#Elliptic Curve Diffie Helman with ed25519
#ecdhgen and ecdhretrieve translated into MiniNero from implementation by TacoTime
import MiniNero
import PaperWallet
def ecdhGen(P):
ephembytes, ephempub = PaperWallet.skpkGen()
sspub = MiniNero.scalarmultKey(P, ephembytes) #(receiver pub) * (sender ecdh sk)
ss1 = MiniNero.cn_fast_hash(sspub)
ss2 = MiniNero.cn_fast_hash(ss1)
return ephembytes, ephempub, ss1, ss2
def ecdhRetrieve(x, pk):
sspub = MiniNero.scalarmultKey(pk, x)
ss1 = MiniNero.cn_fast_hash(sspub)
ss2 = MiniNero.cn_fast_hash(ss1)
return ss1, ss2

View file

@ -0,0 +1,2 @@
import MiniNero
import PaperWallet

View file

@ -0,0 +1,9 @@
import MiniNero
def getHForCT():
A = MiniNero.publicFromInt(123456)
return MiniNero.hashToPoint_ct(A)
H = getHForCT()
for i in range(0, 2**14):
print(MiniNero.scalarmultKeyInt(H, i))

View file

@ -0,0 +1,348 @@
#! /usr/bin/pythonw
# The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
# questions, please refer to our website: http://keccak.noekeon.org/
#
# Implementation by Renaud Bauvin,
# hereby denoted as "the implementer".
#
# To the extent possible under law, the implementer has waived all copyright
# and related or neighboring rights to the source code in this file.
# http://creativecommons.org/publicdomain/zero/1.0/
import math
class KeccakError(Exception):
"""Class of error used in the Keccak implementation
Use: raise KeccakError.KeccakError("Text to be displayed")"""
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class Keccak:
"""
Class implementing the Keccak sponge function
"""
def __init__(self, b=1600):
"""Constructor:
b: parameter b, must be 25, 50, 100, 200, 400, 800 or 1600 (default value)"""
self.setB(b)
def setB(self,b):
"""Set the value of the parameter b (and thus w,l and nr)
b: parameter b, must be choosen among [25, 50, 100, 200, 400, 800, 1600]
"""
if b not in [25, 50, 100, 200, 400, 800, 1600]:
raise KeccakError.KeccakError('b value not supported - use 25, 50, 100, 200, 400, 800 or 1600')
# Update all the parameters based on the used value of b
self.b=b
self.w=b//25
self.l=int(math.log(self.w,2))
self.nr=12+2*self.l
# Constants
## Round constants
RC=[0x0000000000000001,
0x0000000000008082,
0x800000000000808A,
0x8000000080008000,
0x000000000000808B,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008A,
0x0000000000000088,
0x0000000080008009,
0x000000008000000A,
0x000000008000808B,
0x800000000000008B,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800A,
0x800000008000000A,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008]
## Rotation offsets
r=[[0, 36, 3, 41, 18] ,
[1, 44, 10, 45, 2] ,
[62, 6, 43, 15, 61] ,
[28, 55, 25, 21, 56] ,
[27, 20, 39, 8, 14] ]
## Generic utility functions
def rot(self,x,n):
"""Bitwise rotation (to the left) of n bits considering the \
string of bits is w bits long"""
n = n%self.w
return ((x>>(self.w-n))+(x<<n))%(1<<self.w)
def fromHexStringToLane(self, string):
"""Convert a string of bytes written in hexadecimal to a lane value"""
#Check that the string has an even number of characters i.e. whole number of bytes
if len(string)%2!=0:
raise KeccakError.KeccakError("The provided string does not end with a full byte")
#Perform the modification
temp=''
nrBytes=len(string)//2
for i in range(nrBytes):
offset=(nrBytes-i-1)*2
temp+=string[offset:offset+2]
return int(temp, 16)
def fromLaneToHexString(self, lane):
"""Convert a lane value to a string of bytes written in hexadecimal"""
laneHexBE = (("%%0%dX" % (self.w//4)) % lane)
#Perform the modification
temp=''
nrBytes=len(laneHexBE)//2
for i in range(nrBytes):
offset=(nrBytes-i-1)*2
temp+=laneHexBE[offset:offset+2]
return temp.upper()
def printState(self, state, info):
"""Print on screen the state of the sponge function preceded by \
string info
state: state of the sponge function
info: a string of characters used as identifier"""
print("Current value of state: %s" % (info))
for y in range(5):
line=[]
for x in range(5):
line.append(hex(state[x][y]))
print('\t%s' % line)
### Conversion functions String <-> Table (and vice-versa)
def convertStrToTable(self,string):
#Check that input paramaters
if self.w%8!= 0:
raise KeccakError("w is not a multiple of 8")
if len(string)!=2*(self.b)//8:
raise KeccakError.KeccakError("string can't be divided in 25 blocks of w bits\
i.e. string must have exactly b bits")
#Convert
output=[[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0]]
for x in range(5):
for y in range(5):
offset=2*((5*y+x)*self.w)//8
output[x][y]=self.fromHexStringToLane(string[offset:offset+(2*self.w//8)])
return output
def convertTableToStr(self,table):
#Check input format
if self.w%8!= 0:
raise KeccakError.KeccakError("w is not a multiple of 8")
if (len(table)!=5) or (False in [len(row)==5 for row in table]):
raise KeccakError.KeccakError("table must b")
#Convert
output=['']*25
for x in range(5):
for y in range(5):
output[5*y+x]=self.fromLaneToHexString(table[x][y])
output =''.join(output).upper()
return output
def Round(self,A,RCfixed):
"""Perform one round of computation as defined in the Keccak-f permutation
"""
#Initialisation of temporary variables
B=[[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0]]
C= [0,0,0,0,0]
D= [0,0,0,0,0]
#Theta step
for x in range(5):
C[x] = A[x][0]^A[x][1]^A[x][2]^A[x][3]^A[x][4]
for x in range(5):
D[x] = C[(x-1)%5]^self.rot(C[(x+1)%5],1)
for x in range(5):
for y in range(5):
A[x][y] = A[x][y]^D[x]
#Rho and Pi steps
for x in range(5):
for y in range(5):
B[y][(2*x+3*y)%5] = self.rot(A[x][y], self.r[x][y])
#Chi step
for x in range(5):
for y in range(5):
A[x][y] = B[x][y]^((~B[(x+1)%5][y]) & B[(x+2)%5][y])
#Iota step
A[0][0] = A[0][0]^RCfixed
return A
def KeccakF(self,A, verbose=False):
"""Perform Keccak-f function on the state A
verbose: a boolean flag activating the printing of intermediate computations
"""
if verbose:
self.printState(A,"Before first round")
for i in range(self.nr):
#NB: result is truncated to lane size
A = self.Round(A,self.RC[i]%(1<<self.w))
if verbose:
self.printState(A,"Satus end of round #%d/%d" % (i+1,self.nr))
return A
### Padding rule
def pad10star1(self, M, n):
"""Pad M with the pad10*1 padding rule to reach a length multiple of r bits
M: message pair (length in bits, string of hex characters ('9AFC...')
n: length in bits (must be a multiple of 8)
Example: pad10star1([60, 'BA594E0FB9EBBD30'],8) returns 'BA594E0FB9EBBD93'
"""
[my_string_length, my_string]=M
# Check the parameter n
if n%8!=0:
raise KeccakError.KeccakError("n must be a multiple of 8")
# Check the length of the provided string
if len(my_string)%2!=0:
#Pad with one '0' to reach correct length (don't know test
#vectors coding)
my_string=my_string+'0'
if my_string_length>(len(my_string)//2*8):
raise KeccakError.KeccakError("the string is too short to contain the number of bits announced")
nr_bytes_filled=my_string_length//8
nbr_bits_filled=my_string_length%8
l = my_string_length % n
if ((n-8) <= l <= (n-2)):
if (nbr_bits_filled == 0):
my_byte = 0
else:
my_byte=int(my_string[nr_bytes_filled*2:nr_bytes_filled*2+2],16)
my_byte=(my_byte>>(8-nbr_bits_filled))
my_byte=my_byte+2**(nbr_bits_filled)+2**7
my_byte="%02X" % my_byte
my_string=my_string[0:nr_bytes_filled*2]+my_byte
else:
if (nbr_bits_filled == 0):
my_byte = 0
else:
my_byte=int(my_string[nr_bytes_filled*2:nr_bytes_filled*2+2],16)
my_byte=(my_byte>>(8-nbr_bits_filled))
my_byte=my_byte+2**(nbr_bits_filled)
my_byte="%02X" % my_byte
my_string=my_string[0:nr_bytes_filled*2]+my_byte
while((8*len(my_string)//2)%n < (n-8)):
my_string=my_string+'00'
my_string = my_string+'80'
return my_string
def Keccak(self,M,r=1024,c=512,n=1024,verbose=False):
"""Compute the Keccak[r,c,d] sponge function on message M
M: message pair (length in bits, string of hex characters ('9AFC...')
r: bitrate in bits (defautl: 1024)
c: capacity in bits (default: 576)
n: length of output in bits (default: 1024),
verbose: print the details of computations(default:False)
"""
#Check the inputs
if (r<0) or (r%8!=0):
raise KeccakError.KeccakError('r must be a multiple of 8 in this implementation')
if (n%8!=0):
raise KeccakError.KeccakError('outputLength must be a multiple of 8')
self.setB(r+c)
if verbose:
print("Create a Keccak function with (r=%d, c=%d (i.e. w=%d))" % (r,c,(r+c)//25))
#Compute lane length (in bits)
w=(r+c)//25
# Initialisation of state
S=[[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0]]
#Padding of messages
P = self.pad10star1(M, r)
if verbose:
print("String ready to be absorbed: %s (will be completed by %d x '00')" % (P, c//8))
#Absorbing phase
for i in range((len(P)*8//2)//r):
Pi=self.convertStrToTable(P[i*(2*r//8):(i+1)*(2*r//8)]+'00'*(c//8))
for y in range(5):
for x in range(5):
S[x][y] = S[x][y]^Pi[x][y]
S = self.KeccakF(S, verbose)
if verbose:
print("Value after absorption : %s" % (self.convertTableToStr(S)))
#Squeezing phase
Z = ''
outputLength = n
while outputLength>0:
string=self.convertTableToStr(S)
Z = Z + string[:r*2//8]
outputLength -= r
if outputLength>0:
S = self.KeccakF(S, verbose)
# NB: done by block of length r, could have to be cut if outputLength
# is not a multiple of r
if verbose:
print("Value after squeezing : %s" % (self.convertTableToStr(S)))
return Z[:2*n//8]

View file

@ -0,0 +1,96 @@
Content
-------
List of files:
- Keccak.py : the Keccak and KeccakError classes
- demo_KeccakF.py : example of use of Keccak_f function on a 0-filled 5×5 matrix
- demo_TestVectors.py : verification of Short/Long test vectors. The test vectors must be copied in the same location as the Python files
Few words of explanation
------------------------
The Keccak module is stateless. It takes your inputs, performs the computation and returns the result.
Typical uses
------------
1) Compute a hash using Keccak[r=1152, c=448] (224 bits of output) on '00112233445566778899AABBCCDDEEFF' (8*16bits=128 bits)
>>> import Keccak
>>> myKeccak=Keccak.Keccak()
>>> myKeccak.Keccak((128,'00112233445566778899AABBCCDDEEFF'),1152,448,224,True)
Create a Keccak function with (r=1152, c=448 (i.e. w=64))
String ready to be absorbed: 00112233445566778899AABBCCDDEEFF0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 (will be completed by 56 x '00')
Current value of state: Before first round
['0x7766554433221100', '0xffeeddccbbaa9988', '0x1', '0x0', '0x0']
['0x0', '0x0', '0x0', '0x0', '0x0']
['0x0', '0x0', '0x0', '0x0', '0x0']
['0x0', '0x0', '0x8000000000000000', '0x0', '0x0']
['0x0', '0x0', '0x0', '0x0', '0x0']
Current value of state: Satus end of round #1/24
['0xdc77ae5456dd06dd', '0x2110377665444332', '0x7e6e5e6e7e6e5e6e', '0x8019e64c44470000', '0xba208b329807a91']
['0x5669988982a11005', '0xa8864666600eeaaa', '0xe3304ddaaffcc99e', '0x42206eecc2a88664', '0xb77bbffbb77bbffb']
['0x1111111110111117', '0x371dfb48ae8462d1', '0x224555108b45ff10', '0xddba8867553200ef', '0x4c3bf7a26e19d5e']
['0xcb3621d00772611c', '0x13f17c0eb95b8bb5', '0x985510cc88440ddd', '0x2cd47cc54bb25aa3', '0x35c1100ff8899883']
['0x5deab70448bfe251', '0x88a62388992232cc', '0x7788547722dd0032', '0x8804819c9915908c', '0xdd995510cc88440d']
<...>
Current value of state: Satus end of round #24/24
['0xd89c919ce8078903', '0x92ff885abc7f0af9', '0xa0cdebf3ae8d1078', '0xde568902e183b3ce', '0xe3d1096857dc5b35']
['0xc5f432f2633d3da0', '0x6a0094e2d96f8f35', '0xff92be8c648edc5a', '0xb87fe7012b84523a', '0xb8b7e144e77b3096']
['0xf4832b396a99f318', '0xd8c10bcbaed2e2cf', '0x7d0f5ff34fc95a2e', '0x404281a6b9b3c2a2', '0xa758a863c74aecbe']
['0x5b0f0672fcebc63e', '0xfca88e2204aa233e', '0xb62ef1ba33bc5a69', '0x795abef031f2d7dd', '0x7b7dc16e91fff6cd']
['0x677823df6ebd0544', '0xd2a1fc63c7702e0e', '0x49b07e16adc62d95', '0x6bdb0b4f074e8b2b', '0xc27f39383b4799b5']
Value after absorption : 038907E89C919CD8F90A7FBC5A88FF9278108DAEF3EBCDA0CEB383E1028956DE355BDC576809D1E3A03D3D63F232F4C5358F6FD9E294006A5ADC8E648CBE92FF3A52842B01E77FB896307BE744E1B7B818F3996A392B83F4CFE2D2AECB0BC1D82E5AC94FF35F0F7DA2C2B3B9A6814240BEEC4AC763A858A73EC6EBFC72060F5B3E23AA04228EA8FC695ABC33BAF12EB6DDD7F231F0BE5A79CDF6FF916EC17D7B4405BD6EDF2378670E2E70C763FCA1D2952DC6AD167EB0492B8B4E074F0BDB6BB599473B38397FC2
Value after squeezing : 038907E89C919CD8F90A7FBC5A88FF9278108DAEF3EBCDA0CEB383E1028956DE355BDC576809D1E3A03D3D63F232F4C5358F6FD9E294006A5ADC8E648CBE92FF3A52842B01E77FB896307BE744E1B7B818F3996A392B83F4CFE2D2AECB0BC1D82E5AC94FF35F0F7DA2C2B3B9A6814240BEEC4AC763A858A73EC6EBFC72060F5B3E23AA04228EA8FC695ABC33BAF12EB6DDD7F231F0BE5A79CDF6FF916EC17D7B4405BD6EDF2378670E2E70C763FCA1D2952DC6AD167EB0492B8B4E074F0BDB6BB599473B38397FC2
'038907E89C919CD8F90A7FBC5A88FF9278108DAEF3EBCDA0CEB383E1'
2) Computation of the Keccak-f function on an all-zero state
>>> import Keccak
>>> A=[[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,0]]
>>> myKeccak=Keccak.Keccak(1600)
>>> myKeccak.Keccakf(A, True)
>>> myKeccak.printState(A,'Final result')
Current value of state: Before first round
['0x0', '0x0', '0x0', '0x0', '0x0']
['0x0', '0x0', '0x0', '0x0', '0x0']
['0x0', '0x0', '0x0', '0x0', '0x0']
['0x0', '0x0', '0x0', '0x0', '0x0']
['0x0', '0x0', '0x0', '0x0', '0x0']
Current value of state: Satus end of round #1/24
['0x1L', '0x0L', '0x0L', '0x0L', '0x0L']
['0x0L', '0x0L', '0x0L', '0x0L', '0x0L']
['0x0L', '0x0L', '0x0L', '0x0L', '0x0L']
['0x0L', '0x0L', '0x0L', '0x0L', '0x0L']
['0x0L', '0x0L', '0x0L', '0x0L', '0x0L']
<...>
Current value of state: Satus end of round #24/24
['0xf1258f7940e1dde7L', '0x84d5ccf933c0478aL', '0xd598261ea65aa9eeL', '0xbd1547306f80494dL', '0x8b284e056253d057L']
['0xff97a42d7f8e6fd4L', '0x90fee5a0a44647c4L', '0x8c5bda0cd6192e76L', '0xad30a6f71b19059cL', '0x30935ab7d08ffc64L']
['0xeb5aa93f2317d635L', '0xa9a6e6260d712103L', '0x81a57c16dbcf555fL', '0x43b831cd0347c826L', '0x1f22f1a11a5569fL']
['0x5e5635a21d9ae61L', '0x64befef28cc970f2L', '0x613670957bc46611L', '0xb87c5a554fd00ecbL', '0x8c3ee88a1ccf32c8L']
['0x940c7922ae3a2614L', '0x1841f924a2c509e4L', '0x16f53526e70465c2L', '0x75f644e97f30a13bL', '0xeaf1ff7b5ceca249L']
[[17376452488221285863L, 18417369716475457492L, 16959053435453822517L, 424854978622500449L, 10668034807192757780L], [9571781953733
019530L, 10448040663659726788L, 12224711289652453635L, 7259519967065370866L, 1747952066141424100L], [15391093639620504046L, 101139
17136857017974L, 9342009439668884831L, 7004910057750291985L, 1654286879329379778L], [13624874521033984333L, 12479658147685402012L,
4879704952849025062L, 13293599522548616907L, 8500057116360352059L], [10027350355371872343L, 3500241080921619556L, 140226327413610
143L, 10105770293752443592L, 16929593379567477321L]]

View file

@ -0,0 +1,110 @@
import Crypto.Random.random as rand
import itertools
import math #for log
import sys
def decomposition(i):
#from stack exchange, don't think it's uniform
while i > 0:
n = rand.randint(1, i)
yield n
i -= n
def Decomposition(i):
while True:
l = list(decomposition(i))
if len(set(l)) == len(l):
return l
def decomposition2(n, s, d, k):
#home-brewed, returns no duplicates, includes the number d
s = s - 1
n = n
while True:
a = [d]
nn = n
#a.append(d)
for i in range(0, s):
a.append(rand.randint(0, n))
a.sort()
#print("a", a)
b = []
c = []
while len(a) > 0:
t = a.pop()
#print(t, a)
if t >= d:
b.append(nn - t)
else:
c.append(nn - t)
nn = t
c.append(nn)
tot = b[:] + c[:]
#print("b", b)
if sum(set(tot)) == n and len(c) > int(k):
return sorted(c), sorted(b)
def decomposition3(n, s, d, k):
#a combination of both methods, designed to get some smaller values
send, change = decomposition2(n, s, d, k)
for i in send:
if i > n / s:
send.remove(i)
send = send + list(Decomposition(i))
for i in change:
if i > n / (s - 1):
change.remove(i)
change = change + list(Decomposition(i))
return send, change
def divv(l, m):
return [a /float( m) for a in l]
def frexp10(x):
exp = int(math.log10(x))
return x / 10**exp, exp
def decideAmounts(totalInputs, toSend, Partitions, k, fuzz):
#fuzz is an optional amount to fuzz the transaction by
#so if you start with a big obvious number like 2000, it might be fuzzed by up to "fuzz" amount
fz = rand.randint(0, int(fuzz * 1000) ) / 1000.0
toSend += fz
g, ii =frexp10(totalInputs)
ii = 10 ** (-1 * min(ii - 2, 0))
print("ii", ii)
M = 10 ** (int(math.log(2 ** Partitions) / math.log(10))) * ii
#M = 10 ** M
print("multiplier:", M)
totalInputs = int(totalInputs * M)
toSend = int(toSend * M)
change = totalInputs - toSend
send_amounts, change_amounts = decomposition3(totalInputs, Partitions, toSend, k)
all_amounts = send_amounts[:] + change_amounts[:]
rand.shuffle(all_amounts)
print("")
print("change amounts:", divv(change_amounts, M))
print("send amounts:", divv(send_amounts, M))
print("now from the following, how much is sent?")
print("all amounts:", sorted(divv(all_amounts, M)))
print("possible sent amounts:")
amounts = []
for L in range(0, len(all_amounts)+1):
for subset in itertools.combinations(all_amounts, L):
amounts.append(sum(subset))
print("number of possible sent amounts:")
print(len(amounts))
print("2^N:", 2 ** len(all_amounts))
print("number of possible sent amounts duplicates removed:")
print(len(list(set(amounts))))
if len(sys.argv) > 2:
kk = 2
parts = 7
kk = rand.randint(1, int(parts / 4)) #how many sends to demand
fuzz = 1
decideAmounts(float(sys.argv[1]), float(sys.argv[2]), parts, kk, fuzz)

View file

@ -0,0 +1,55 @@
#see mrl_notes .. obv this is a work in progress
import MiniNero
import PaperWallet
def keyImage(x):
HP = MiniNero.hashToPoint_ct(MiniNero.scalarmultBase(x))
return MiniNero.scalarmultKey(HP, x)
def LLW_Sig(pk, xx, index ):
n = len(pk)
print("Generating LLW sig of length ", n)
L = [None] * n
R = [None] * n
c= [None] * n
s = [PaperWallet.skGen() for i in range(0, n)]
HP = [MiniNero.hashToPoint_ct(i) for i in pk]
pj = ''.join(pk)
keyimage = keyImage(xx) #ok
s[index] = MiniNero.mul_8(s[index])
L[index] = MiniNero.scalarmultBase(s[index])
R[index] = MiniNero.scalarmultKey(HP[index], s[index]) #aH
j = (index + 1) % n
c[j] = MiniNero.cn_fast_hash(pj+L[index]+R[index])
while j != index:
L[j] = MiniNero.addKeys(MiniNero.scalarmultBase(s[j]), MiniNero.scalarmultKey(pk[j], c[j])) #Lj = sG + cxG
R[j] = MiniNero.addKeys(MiniNero.scalarmultKey(HP[j], s[j]), MiniNero.scalarmultKey(keyimage, c[j])) #Rj = sH + cxH
cj = (j + 1) % n
c[cj] = MiniNero.cn_fast_hash(pj + L[j] + R[j]) #c j+1 = H(pk + Lj + Rj
j = cj #increment j
s[index] = MiniNero.sc_mulsub_keys(s[index], c[index], xx) #si = a - c x so a = s + c x
print("sigma = ", keyimage, c[0], s[:])
return keyimage, c[0], s[:]
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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,85 @@
#see https://eprint.iacr.org/2015/1098.pdf
import MiniNero
import PaperWallet
def keyVector(rows):
return [None] * rows
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 MLSAG_Sign(pk, xx, index):
rows = len(xx)
cols = len(pk[0])
print("Generating MLSAG sig of dimensions ",rows ,"x ", cols)
L = [[None] * cols] #list of keyvectors? except it's indexed by cols... it's kind of internal actually
R = [[None] * cols]
s = [[PaperWallet.skGen() for i in range(0, cols)] ] #first index is rows, second is cols, wonder if I should switch that..
HP = [[MiniNero.hashToPoint_cn(i) for i in pk[0]]]
pj = ''.join(pk[0])
for i in range(1, rows):
L.append([None] * cols)
R.append([None] * cols)
s.append([PaperWallet.skGen() for j in range(0, cols)])
HP.append([MiniNero.hashToPoint_cn(j) for j in pk[i]])
pj = pj + ''.join(pk[i])
c= [None] * cols #1-dimensional
keyimage = keyImage(xx, rows) #ok
for i in range(0, rows):
L[i][index] = MiniNero.scalarmultBase(s[i][index]) #aG
R[i][index] = MiniNero.scalarmultKey(HP[i][index], s[i][index]) #aH
j = (index + 1) % cols
tohash = pj
for i in range(0, rows):
tohash = tohash + L[i][index] + R[i][index]
c[j] = MiniNero.cn_fast_hash(tohash)
while j != index:
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])) #Lj = sG + cxG
R[i][j] = MiniNero.addKeys(MiniNero.scalarmultKey(HP[i][j], s[i][j]), MiniNero.scalarmultKey(keyimage[i], c[j])) #Rj = sH + cxH
tohash = tohash + L[i][j] + R[i][j]
j = (j + 1) % cols
c[j] = MiniNero.cn_fast_hash(tohash)
for i in range(0, rows):
s[i][index] = MiniNero.sc_mulsub_keys(s[i][index], c[index], xx[i]) #si = a - c x so a = s + c x
return keyimage, c[0], s
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

View file

@ -0,0 +1,100 @@
#see https://eprint.iacr.org/2015/1098.pdf
#this one is same as MLSAG.py, I'm just experimenting with
#how to best implement it..
import MiniNero
import PaperWallet
def keyVector(rows):
return [None] * rows
def keyMatrix(rows, cols):
#first index is columns (so slightly backward from math)
rv = [None] * cols
for i in range(0, cols):
rv[i] = keyVector(rows)
return rv
def hashKeyVector(v):
return [MiniNero.hashToPoint_cn(vi) for vi in v]
def vScalarMultBase(v):
return [MiniNero.scalarmultBase(a) for a in v]
def keyImageV(x):
#takes as input a keyvector, returns the keyimage-vector
return [MiniNero.scalarmultKey(MiniNero.hashToPoint_cn(MiniNero.scalarmultBase(xx)), xx) for xx in x]
def skvGen(n):
return [PaperWallet.skGen() for i in range(0, n)]
def skmGen(r, c):
rv = keyMatrix(r, c)
for i in range(0, c):
rv[i] = skvGen(r)
return rv
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 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])

View file

@ -0,0 +1,261 @@
#"MiniNero" by Shen Noether mrl. Use at your own risk.
import hashlib #for signatures
import math
import Crypto.Random.random as rand
import Keccak #cn_fast_hash
import mnemonic #making 25 word mnemonic to remember your keys
import binascii #conversion between hex, int, and binary. Also for the crc32 thing
import ed25519 #Bernsteins python ed25519 code from cr.yp.to
import zlib
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
def netVersion():
return "12"
def public_key(sk):
#returns point encoded to binary .. sk is just an int..
return ed25519.encodepoint(ed25519.scalarmultbase(sk)) #pub key is not just x coord..
def scalarmult_simple(pk, num):
#returns point encoded to hex.. num is an int, not a hex
return ed25519.encodepoint(ed25519.scalarmult(toPoint(pk), num)) #pub key is not just x coord..
def addKeys(P1, P2):
return binascii.hexlify(ed25519.encodepoint(ed25519.edwards(toPoint(P1), toPoint(P2))))
#aG + bB, G is basepoint..
def addKeys1(a, b, B):
return addKeys(scalarmultBase(a), scalarmultKey(B, b))
#aA + bB
def addKeys2(a, A, b, B):
return addKeys(scalarmultKey(A, a), scalarmultKey(B, b))
def subKeys(P1, P2):
return binascii.hexlify(ed25519.encodepoint(ed25519.edwards_Minus(toPoint(P1), toPoint(P2))))
def randomScalar():
tmp = rand.getrandbits(32 * 8) # 8 bits to a byte ...
return (tmp)
def xor(a, b):
return intToHex(hexToInt(a) ^ hexToInt(b))
def electrumChecksum(wordlist):
wl = wordlist.split(" ") #make an array
if len(wl) > 13:
wl = wl[:24]
else:
wl = wl[:12]
upl = 3 #prefix length
wl2 = ''
for a in wl:
wl2+= a[:upl]
z = ((zlib.crc32(wl2) & 0xffffffff) ^ 0xffffffff ) >> 0
z2 = ((z ^ 0xffffffff) >> 0) % len(wl)
return wl[z2]
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = len(__b58chars)
def b58encode(v):
a = [reverseBytes(v[i:i+16]) for i in range(0, len(v)-16, 16)]
rr = -2*((len(v) /2 )% 16)
res = ''
for b in a:
bb = hexToInt(b)
result = ''
while bb >= __b58base:
div, mod = divmod(bb, __b58base)
result = __b58chars[mod] + result
bb = div
result = __b58chars[bb] + result
res += result
result = ''
if rr < 0:
bf = hexToInt(reverseBytes(v[rr:])) #since we only reversed the ones in the array..
result = ''
while bf >= __b58base:
div, mod = divmod(bf, __b58base)
result = __b58chars[mod] + result
bf = div
result = __b58chars[bf] + result
res += result
return res
def sc_0():
return intToHex(0)
def sc_reduce_key(a):
return intToHex(hexToInt(a) % l)
def sc_unreduce_key(a):
return intToHex(hexToInt(a) % l + l)
def sc_add_keys(a, b):
#adds two private keys mod l
return intToHex((hexToInt(a) + hexToInt(b)) % l)
def sc_add(a, exps):
#adds a vector of private keys mod l and multiplies them by an exponent
ssum = 0
for i in range(0, len(a)):
ssum = (ssum + 10 ** exps[i] * hexToInt(a[i])) % l
return intToHex(ssum)
def sc_check(a):
if hexToInt(a) % l == 0:
return False
return (a == sc_reduce_key(a))
def addScalars(a, b): #to do: remove above and rename to this (so that there is "add keys" and "add scalars")
#adds two private keys mod l
return intToHex((hexToInt(a) + hexToInt(b)) % l)
def sc_sub_keys(a, b):
#subtracts two private keys mod l
return intToHex((hexToInt(a) - hexToInt(b)) % l)
def sc_mul_keys(a, b):
return intToHex((hexToInt(a) * hexToInt(b)) % l)
def sc_sub_keys(a, b):
return intToHex((hexToInt(a) - hexToInt(b)) % l)
def sc_mulsub_keys(a, b, c):
#returns a - b * c (for use in LLW sigs - see MRL notes v 0.3)
return intToHex( (hexToInt(a)- hexToInt(b) * hexToInt(c)) % l)
def add_l(a, n):
return intToHex(hexToInt(a) +n * l )
def sc_muladd_keys(a, b, c):
#returns a + b * c (for use in LLW sigs - see MRL notes v 0.3)
return intToHex((hexToInt(a)+ hexToInt(b) * hexToInt(c) ) % l)
def mul_8(a):
return intToHex(8 * hexToInt(a))
def fe_reduce_key(a):
return intToHex(hexToInt(a) % q)
def recoverSK(seed):
mn2 = seed.split(" ") #make array
if len(mn2) > 13:
mn2 = mn2[:24]
sk = mnemonic.mn_decode(mn2)
else:
mn2 = mn2[:12]
#mn2 += mn2[:]
sk = cn_fast_hash(mnemonic.mn_decode(mn2))
#sk = mnemonic.mn_decode(mn2)
return sk
def cn_fast_hash(s):
k = Keccak.Keccak()
return k.Keccak((len(s) * 4, s), 1088, 512, 32 * 8, False).lower() #r = bitrate = 1088, c = capacity, n = output length in bits
def getView(sk):
a = hexToInt(cn_fast_hash(sc_reduce_key(sk))) % l
return intToHex(a)
def getViewMM(sk):
a = hexToInt(cn_fast_hash(sk))
return intToHex(a)
def reverseBytes(a): #input is byte string, it reverse the endianness
b = [a[i:i+2] for i in range(0, len(a)-1, 2)]
return ''.join(b[::-1])
def encode_addr(version, spendP, viewP):
buf = version + spendP + viewP
h = cn_fast_hash(buf)
buf = buf + h[0:8]
return b58encode(buf)
def hexToInt(h):
s = binascii.unhexlify(h) #does hex to bytes
bb = len(h) * 4 #I guess 8 bits / b
return sum(2**i * ed25519.bit(s,i) for i in range(0,bb)) #does to int
def intToHex(i):
return binascii.hexlify(ed25519.encodeint(i)) #hexlify does bytes to hex
def publicFromSecret(sk):
#returns pubkey in hex, same as scalarmultBase
return binascii.hexlify(public_key(hexToInt(sk)))
def scalarmultBase(sk):
#returns pubkey in hex, expects hex sk
return binascii.hexlify(public_key(hexToInt(sk)))
def identity():
return scalarmultBase(intToHex(0))
def scalarmultKey(pk, num):
return binascii.hexlify(scalarmult_simple(pk, hexToInt(num)))
def scalarmultKeyInt(pk, num):
return binascii.hexlify(scalarmult_simple(pk, num))
def publicFromInt(i):
#returns pubkey in hex, same as scalarmultBase.. should just pick one
return binascii.hexlify(public_key(i))
def toPoint(hexVal):
aa = binascii.unhexlify(hexVal) #to binary (new)
return ed25519.decodepoint(aa) #make to point
def fromPoint(aa): #supposed to reverse toPoint
binvalue = ed25519.encodepoint(aa)
return binascii.hexlify(binvalue)
def hashToPoint_cn(hexVal):
#note this is the monero one, won't work for C.T.
#however there is an alternative which will work for C.T.
#pk = publicFromSecret(hexVal)
HP = cn_fast_hash(hexVal)
return scalarmultBase(HP)
def mul8(point):
return binascii.hexlify(scalarmult_simple(point, 8))
def hashToPoint_ct(hexVal):
#note this is the monero one, won't work for C.T.
#however there is an alternative which will work for C.T.
#returns a hex string, not a point
a = hexVal[:]
i = 0
while True:
worked = 1
a = cn_fast_hash(a)
i += 1
try:
toPoint(a)
except:
worked = 0
if worked == 1:
break
print("found point after "+str(i)+" hashes")
return mul8(a) # needs to be in group of basepoint
def getAddrMM(sk):
vk = getViewMM(sk)
sk = sc_reduce_key(sk)
pk = publicFromSecret(sk)
pvk = publicFromSecret(vk)
return encode_addr(netVersion(), pk, pvk)
def getAddr(sk):
vk = getView(sk)
sk = sc_reduce_key(sk)
pk = publicFromSecret(sk)
pvk = publicFromSecret(vk)
return encode_addr(netVersion(), pk, pvk)

View file

@ -0,0 +1 @@
MiniNeroPk = 'cd9db8fafbf2b99605cee870ada0dd64ae5a583a4414c3d5d34e8e8072d520b6'

View file

@ -0,0 +1,50 @@
# shen noether - mrl
# this python script computes
# a (Keccak) hash of your document
# and then turns it into a monero address
# for timestamping c.f. github.com/ShenNoether/btcProof
#
import MiniNero #for creating monero address
import sys #for getting command line arguments
import binascii #for converting binary data
import Keccak #for hash, we use this instead of sha256
import ed25519
import mnemonic
BLOCKSIZE = 2 **10
l = 2**252 + 27742317777372353535851937790883648493
def cnHashOfFile(filepath):
#c.f. github.com/ShenNoether/btcProof sha256OfFile
bin_data = open(filepath, 'rb').read()
hex_data = binascii.hexlify(bin_data)
print(hex_data)
return MiniNero.cn_fast_hash(hex_data)
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)
if len(sys.argv) > 1:
#print("address to send to :", moneroProofOfFile(sys.argv[1]))
cnHashOfFile(sys.argv[1])
else:
print("provide filename as argument")
print("example: MoneroProof.py Keccak.txt")

View file

@ -0,0 +1,19 @@
#use at your own risk
#Note, this is not quite working apparently,
#apparently the viewkeys from the main client and mymonero
#although, if they were derived consistently
#(which seems reasonable) then it should work
import MiniNero
import mnemonic
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)
seed = raw_input("12 words?")
print(importMM(seed))

View file

@ -0,0 +1,97 @@
#Work in progress obvously. This will implement the modified version of gmaxwells Confidential Transactions so that they work with ring signatures.
#The math is outlined in mrl_notes v4 (v3 is same but sign of z should be - in an equation) which can be found in this repository.
import MiniNero
import LLW_Sigs
import PaperWallet
def getHForCT():
A = MiniNero.publicFromInt(1)
return MiniNero.hashToPoint_ct(A)
def binary(n):
b = []
while n:
b = [n & 1] + b
n >>= 1
return b or [0]
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 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 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 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
H_ct = getHForCT()
print("H", H_ct)
a = MiniNero.intToHex(49)
b1 = MiniNero.intToHex(30)
b2 = MiniNero.intToHex(20)
x_priv = PaperWallet.skGen() #our private key
x_commit = PaperWallet.skGen() # our private commitment key
#x_commit = x_priv #do with x_priv = x_commit first... , then modify by adding another mask
Pk1 = MiniNero.scalarmultBase(x_priv) #our public key
Pk2 = MiniNero.scalarmultBase(PaperWallet.skGen()) #other sk (we don't know it
print("xpriv, Pk1, Pk2", x_priv, Pk1, Pk2)
C_out, out_masks, sumMasks, values2 = out_commitments([b1, b2])
#testing rangeProofs
print("testing range proofs")
I_proofs, c0s, ss, Ci_s = rangeProof(values2[0], out_masks[0])
print("Iproofs, c0s, ss", I_proofs, c0s, ss)
print("C_out, outmasks", C_out, sumMasks)
C_in, z = in_commitments(a, x_commit, sumMasks)
print("C_in, z", C_in, z)
I, c0, s, PP = CT_ring_sig([Pk1, Pk2], C_in, C_out, MiniNero.sc_add_keys(x_priv,z), 0)
LLW_Sigs.LLW_Ver(PP, I, c0, s)

View file

@ -0,0 +1,60 @@
#monero paper wallet test code, shen noether mrl
#use at your own risk
import Crypto.Random.random as rand
import MiniNero
import mnemonic
l = 2**252 + 27742317777372353535851937790883648493
def skGen():
return MiniNero.intToHex( 8 * (rand.getrandbits(64 * 8)) % l)
def pkGen():
#The point of this is in testing functions where you need some arbitrary public key to test against
return MiniNero.scalarmultBase(MiniNero.intToHex( 8 * (rand.getrandbits(64 * 8)) % l))
def skpkGen():
#The point of this is in testing functions where you need some arbitrary public key to test against
sk = skGen()
return sk, MiniNero.scalarmultBase(sk)
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
if __name__ == "__main__":
keysBoth()

View file

@ -0,0 +1,143 @@
#!/usr/bin/python
import sys #for arguments
import MiniNero
import mnemonic
import PaperWallet
import Ecdh
import ASNL
import MLSAG
import MLSAG2
import LLW_Sigs
import RingCT
import Crypto.Random.random as rand
import Translator
import binascii
import RingCT2
#Schnorr NonLinkable true one and false one
x, P1 = PaperWallet.skpkGen()
P2 = PaperWallet.pkGen()
P3 = PaperWallet.pkGen()
L1, s1, s2 = ASNL.GenSchnorrNonLinkable(x, P1, P2, 0)
print("Testing Schnorr Non-linkable!")
print("This one should verify!")
print(ASNL.VerSchnorrNonLinkable(P1, P2, L1, s1, s2))
print("")
print("This one should NOT verify!")
print(ASNL.VerSchnorrNonLinkable(P1, P3, L1, s1, s2))
#ASNL true one, false one, C != sum Ci, and one out of the range..
print("\n\n\nTesting ASNL")
N = 10
x = [None] * N
P1 = [None] * N
P2 = [None] * N
indi = [None] * N
for j in range(0, N):
indi[j] = rand.getrandbits(1)
x[j] = PaperWallet.skGen()
if indi[j] == 0:
P1[j] = MiniNero.scalarmultBase(x[j])
P2[j] = PaperWallet.pkGen()
else:
P2[j] = MiniNero.scalarmultBase(x[j])
P1[j] = PaperWallet.pkGen()
L1, s2, s = ASNL.GenASNL(x, P1, P2, indi)
#true one
print("This one should verify!")
ASNL.VerASNL(P1, P2, L1, s2, s)
#false one
indi[3] = (indi[3] + 1) % 2
print("")
print("This one should NOT verify!")
L1, s2, s = ASNL.GenASNL(x, P1, P2, indi)
ASNL.VerASNL(P1, P2, L1, s2, s)
#MG sig: true one
print("\n\n\nTesting MG Sig: this one should verify!")
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
for j in range(0, N):
x[j] = [None] * R
P[j] = [None] * R
for i in range(0, R):
x[j][i] = PaperWallet.skGen()
P[j][i] = MiniNero.scalarmultBase(x[j][i])
for j in range(0, R):
sk[j] = x[j][ind]
print("x", x)
II, cc, ss = MLSAG.MLSAG_Sign(P, sk, ind)
print("Sig verified?", MLSAG.MLSAG_Ver(P, II, cc, ss) )
#MG sig: false one
print("\n\nMG Sig: this one should NOT verify!")
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
for j in range(0, N):
x[j] = [None] * R
P[j] = [None] * R
for i in range(0, R):
x[j][i] = PaperWallet.skGen()
P[j][i] = MiniNero.scalarmultBase(x[j][i])
for j in range(0, R):
sk[j] = x[j][ind]
sk[2] = PaperWallet.skGen() #assume we don't know one of the secret keys
print("x", x)
II, cc, ss = MLSAG.MLSAG_Sign(P, sk, ind)
print("Sig verified?", MLSAG.MLSAG_Ver(P, II, cc, ss) )
#rct Sig: range proof true / false, sum Ci true / false, MG sig true / false,
print("\n\n\nTesting Ring CT")
sc = []
pc = []
sctmp, pctmp = RingCT2.ctskpkGen(60)
sc.append(sctmp)
pc.append(pctmp)
sctmp, pctmp = RingCT2.ctskpkGen(70)
sc.append(sctmp)
pc.append(pctmp)
#add output 500
amounts = []
amounts.append(5)
destinations = []
Sk, Pk = PaperWallet.skpkGen()
destinations.append(Pk)
#add output for 12500
amounts.append(125);
Sk, Pk = PaperWallet.skpkGen()
destinations.append(Pk)
s = RingCT2.genRct(sc, pc, destinations, amounts, 2)
print("attempting to verify")
print(RingCT2.verRct(s))
#decode received amount
print("decode amounts working?")
print(RingCT2.decodeRct(s, Sk, 0))
print("decode amounts working?")
print(RingCT2.decodeRct(s, Sk, 1))

View file

@ -0,0 +1,123 @@
import MiniNero
import MLSAG
import LLW_Sigs
import PaperWallet
import AggregateSchnorr
import Ecdh
import Translator
def getHForCT():
return "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94"
A = MiniNero.publicFromInt(1)
H = MiniNero.hashToPoint_ct(A)
Translator.hexToC(H)
print(H)
return H
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 binary(n, digits):
b = [0] * digits
i = 0
while n:
b[i] = n & 1
i = i + 1
n >>= 1
return b
#unused? (Maybe I was just using for testing..)
def dec(binArray):
s = 0
i = 0
for a in binArray:
s = s + a * 2 ** i
i+= 1
return s
def sumCi(Cis):
CSum = MiniNero.identity()
for i in Cis:
CSum = MiniNero.addKeys(CSum, i)
return CSum
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 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 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)
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

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,5 @@
724
0
('checksum', '`\xb1w\xce')
1FpHkeBrkjffXd37y7bwa7gBJDUnvSrkS1
https://blockchain.info/address/1FpHkeBrkjffXd37y7bwa7gBJDUnvSrkS1

Binary file not shown.

View file

@ -0,0 +1,6 @@
943
0
('checksum', 'E\xc1Lg')
1N8g2cVBnZvq7GrfvTrmWTqXwPQZhAghf4
https://blockchain.info/address/1N8g2cVBnZvq7GrfvTrmWTqXwPQZhAghf4
Created new window in existing browser session.

Binary file not shown.

View file

@ -0,0 +1,5 @@
811
0
('checksum', '\x9e\xb9\xce\xc4')
12ioqmWrLT5rjH3eDcgra2Bog6AfXDd83u
https://blockchain.info/address/12ioqmWrLT5rjH3eDcgra2Bog6AfXDd83u

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,331 @@
import MiniNero
import MLSAG2
import PaperWallet
import AggregateSchnorr
import Ecdh
import Crypto.Random.random as rand
#set 8 atoms, since python is super slow on my laptop - normally this is 64 (note these range sigs are going pretty fast in the c++ version)
ATOMS = 8
#implementing some types
class ctkey(object):
__slots__ = ['dest', 'mask']
def ctkeyV(rows):
return [ctkey() for i in range(0, rows)]
class ecdhTuple(object):
__slots__ = ['mask', 'amount','senderPk']
class asnlSig(object):
__slots__ = ['L1', 's2','s']
class mgSig(object):
__slots__ = ['ss', 'cc','II']
class rangeSig(object):
__slots__ = ['asig', 'Ci']
class rctSig(object):
__slots__ = ['rangeSigs', 'MG', 'mixRing', 'ecdhInfo','outPk']
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 getHForCT():
return "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94"
A = MiniNero.publicFromInt(1)
H = MiniNero.hashToPoint_ct(A)
Translator.hexToC(H)
print(H)
return H
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 d2b(n, digits):
b = [0] * digits
i = 0
while n:
b[i] = n & 1
i = i + 1
n >>= 1
return b
def b2d(binArray):
s = 0
i = 0
for a in binArray:
s = s + a * 2 ** i
i+= 1
return s
def sumCi(Cis):
CSum = MiniNero.identity()
for i in Cis:
CSum = MiniNero.addKeys(CSum, i)
return CSum
#proveRange and verRange
#proveRange gives C, and mask such that \sumCi = C
# c.f. http:#eprint.iacr.org/2015/1098 section 5.1
# and Ci is a commitment to either 0 or 2^i, i=0,...,63
# thus this proves that "amount" is in [0, 2^ATOMS]
# mask is a such that C = aG + bH, and b = amount
#verRange verifies that \sum Ci = C and that each Ci is a commitment to 0 or 2^i
#"prove" returns a rangeSig (list) containing a list [L1, s2, s] and a key64 list [C0, C1, ..., C64] of keys, it also returns C = sum(Ci) and mask, which in the c++ version are returned by reference
#inputs key C, key mask, number amount
#"ver" returns true or false, and inputs a key, and a rangesig list "as"
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 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)
#Ring-ct MG sigs
#Prove:
# c.f. http:#eprint.iacr.org/2015/1098 section 4. definition 10.
# This does the MG sig on the "dest" part of the given key matrix, and
# the last row is the sum of input commitments from that column - sum output commitments
# this shows that sum inputs = sum outputs
#Ver:
# verifies the above sig is created corretly
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 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)
#These functions get keys from blockchain
#replace these when connecting blockchain
#getKeyFromBlockchain grabs a key from the blockchain at "reference_index" to mix with
#populateFromBlockchain creates a keymatrix with "mixin" columns and one of the columns is inPk
# the return value are the key matrix, and the index where inPk was put (random).
def getKeyFromBlockchain(reference_index):
#returns a ctkey a (randomly)
rv = ctkey()
rv.dest = PaperWallet.pkGen()
rv.mask = PaperWallet.pkGen()
return rv
def populateFromBlockchain(inPk, mixin):
#returns a ckKeyMatrix with your public input keys at "index" which is the second returned parameter.
#the returned ctkeyMatrix will have number of columns = mixin
rv = [None] * mixin
index = rand.getrandbits(mixin - 1)
blockchainsize = 10000
for j in range(0, mixin):
if j != index:
rv[j] = [getKeyFromBlockchain(rand.getrandbits(blockchainsize)) for i in range(0, len(inPk))]
else:
rv[j] = inPk
return rv, index
#Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
# where C= aG + bH
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 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
#RingCT protocol
#genRct:
# creates an rctSig with all data necessary to verify the rangeProofs and that the signer owns one of the
# columns that are claimed as inputs, and that the sum of inputs = sum of outputs.
# Also contains masked "amount" and "mask" so the receiver can see how much they received
#verRct:
# verifies that all signatures (rangeProogs, MG sig, sum inputs = outputs) are correct
#decodeRct: (c.f. http:#eprint.iacr.org/2015/1098 section 5.1.1)
# uses the attached ecdh info to find the amounts represented by each output commitment
# must know the destination private key to find the correct amount, else will return a random number
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 verRct(rv):
#inputs:
#rv 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)
#outputs:
#true or false
rvb = True
tmp = True
for i in range(0, len(rv.outPk)):
tmp = verRange(rv.outPk[i].mask, rv.rangeSigs[i])
print(tmp)
rvb = rvb and tmp
mgVerd = verRctMG(rv.MG, rv.mixRing, rv.outPk)
print(mgVerd)
return (rvb and mgVerd)
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)

View file

@ -0,0 +1,23 @@
('H', '61fe7f0f5a607a33427d01dd1fded5ffa03fae2e9df9ebccf2e0a2f5bd77a204')
inputs
('b, b in binary', 10000, [0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1])
Generating Aggregate Schnorr Non-linkable Ring Signature
outputs
('b, b in binary', 7000, [0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0])
Generating Aggregate Schnorr Non-linkable Ring Signature
('b, b in binary', 3000, [0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0])
Generating Aggregate Schnorr Non-linkable Ring Signature
verifying range proofs of outputs
Verifying Aggregate Schnorr Non-linkable Ring Signature
Verified
Verifying Aggregate Schnorr Non-linkable Ring Signature
Verified
('Generating MLSAG sig of dimensions ', 2, 'x ', 2)
('verifying MLSAG sig of dimensions ', 2, 'x ', 2)
('c', ['80a3cfd06dd2862307cd75c2a1566f20cd743dbb0b9feb22d79dcbecb9023f42', 'a9b7342ba7bf2f102505ca19dab734fde638916c0a29f5b30e49833ab51393ea', '80a3cfd06dd2862307cd75c2a1566f20cd743dbb0b9feb22d79dcbecb9023f42'])
('sig verifies?', True)
('Sig verified?', True)
Finding received amount corresponding to Cib
('received ', 7000, 'a488ec68732fb551841c2c6dcc7ffac895d98ec7e9378275ed20ea12805fc18e')
Finding received amount corresponding to Cic
('received ', 3000, '1b46626858e130a0f3884c74c9fdeabc4d812c519103ea16a35a3f82a3d0ed6d')

View file

@ -0,0 +1,8 @@
import MiniNero
import MLSAG2
import PaperWallet
import AggregateSchnorr
import Ecdh
import Crypto.Random.random as rand
#def Initiate(skIn, pkIn, pkOut,

View file

@ -0,0 +1,17 @@
import MiniNero
import ed25519
import binascii
import PaperWallet
import cherrypy
import os
import time
import bitmonerod
import SimpleXMR2
xmr_addr = "44TVPcCSHebEQp4LnapPkhb2pondb2Ed7GJJLc6TkKwtSyumUnQ6QzkCCkojZycH2MRfLcujCM7QR1gdnRULRraV4UpB5n4"
xmr_amount = "0.25"
xmr_pid = "d8dd8f42cb13f26dbbf86d2d1da061628cdd17781be95e58a21c845465a2c7f6"
bitmonerod.send(xmr_addr, float(xmr_amount), xmr_pid, 3)

View file

@ -0,0 +1,35 @@
import MiniNero
import os
import ed25519
import binascii
import PaperWallet
import json, hmac, hashlib, time, requests
def HexSigningPubKey(s):
return binascii.hexlify(ed25519.publickey(ed25519.encodeint(MiniNero.hexToInt(s))))
def Signature(m, sk):
sk2 = ed25519.encodeint(MiniNero.hexToInt(sk))
pk = ed25519.publickey(sk2)
return binascii.hexlify(ed25519.signature(m, sk2, pk))
def Verify(sig, m, pk):
return ed25519.checkvalid(binascii.unhexlify(sig), m, binascii.unhexlify(pk))
#get saved access pubkey
from MiniNeroPubKey import *
pubkey = MiniNeroPk
#ip = raw_input('ip of your server\n')
ip = '192.168.2.112:8080' #hopefully you save this in your app...
ip = '192.168.137.235:8080'
ip = raw_input('your ip?\n')
ip = ip + ':8080'
#sec = raw_input('you secret key?\n')
timestamp = str(int(time.time()))
r = requests.get("http://"+ip +'/api/mininero/')
print r.text
print("your time - server time is:", int(time.time()) - int(r.text))

View file

@ -0,0 +1,57 @@
import MiniNero
import os
import ed25519
import binascii
import PaperWallet
import json, hmac, hashlib, time, requests
def HexSigningPubKey(s):
return binascii.hexlify(ed25519.publickey(ed25519.encodeint(MiniNero.hexToInt(s))))
def Signature(m, sk):
sk2 = ed25519.encodeint(MiniNero.hexToInt(sk))
pk = ed25519.publickey(sk2)
return binascii.hexlify(ed25519.signature(m, sk2, pk))
def Verify(sig, m, pk):
return ed25519.checkvalid(binascii.unhexlify(sig), m, binascii.unhexlify(pk))
def offset(ip):
timestamp = str(int(time.time()))
r = requests.get("http://"+ip +'/api/mininero/')
print r.text
print("your time - server time is:", int(time.time()) - int(r.text))
return int(time.time()) - int(r.text)
#get saved access pubkey
from MiniNeroPubKey import *
pubkey = MiniNeroPk
#ip = raw_input('ip of your server\n')
ip = '192.168.2.112:8080' #hopefully you save this in your app...
ip = '192.168.137.235:8080'
ip = raw_input('your ip?\n')
ip = ip + ':8080'
sec = raw_input('you secret key?\n')
timestamp = str(int(time.time()) - offset(ip))
Type = "send"
amount = "0.1"
destination="1em2WCg9QKxRxbo6S3xKF2K4UDvdu6hMc" #just a random one, I think it's the hash of mininero.py
#this should be base 64...
message = Type+amount.replace('.', 'd')+timestamp+destination
sig = Signature(message, sec)
tx = {
'Type': Type,
'timestamp' : timestamp,
'destination': destination,
'signature': sig,
'amount': amount,
}
#print("curl -d Type='"+Type+"' -d signature='"+sig+"' -d timestamp='"+timestamp+"' -d destination='"+destination+"' -d amount='"+amount+"' -X POST '"+ip+"/api/mininero/'")
r = requests.post("http://"+ip +'/api/mininero/', data=tx)
print r.text

View file

@ -0,0 +1,88 @@
import MiniNero
import ed25519
import binascii
import PaperWallet
import cherrypy
import os
import time
import bitmonerod
import SimpleXMR2
def HexSigningPubKey(s):
return binascii.hexlify(ed25519.publickey(ed25519.encodeint(MiniNero.hexToInt(s))))
def Signature(m, sk):
#note this seems to return nicely sized version of the signature
#contrast with, i.e. tweetnacl..
sk2 = ed25519.encodeint(MiniNero.hexToInt(sk))
pk = ed25519.publickey(sk2)
return binascii.hexlify(ed25519.signature(m, sk2, pk))
def Verify(sig, m, pk):
return ed25519.checkvalid(binascii.unhexlify(sig), m, binascii.unhexlify(pk))
class MiniNeroServer:
exposed = True
def GET(self, id=None):
times = str(int(time.time()))
return (times)
def POST(self, signature, Type, timestamp, amount=None, destination=None, pid=None, mixin=None):
times= int(time.time())
pubkey = MiniNeroPk
message = Type+amount.replace('.', 'd')+timestamp+destination
ver = Verify(signature.encode("utf8"), message.encode("utf8"), pubkey)
if abs(times - int(timestamp)) > 30:
ver = False
return ('fail based on timestamp too old')
if Type == 'address':
if (ver):
print("do rpc call")
#bitmonerod.myAddress()
return ("Your Address is ")
if Type == 'balance':
if (ver):
print("do rpc call")
#bitmonerod.myAddress()
return ('your balance is ??')
if Type == 'send':
if (ver) :
#create xmr2 order async, return uuid
uuid, xmr_amount, xmr_addr, xmr_pid = SimpleXMR2.btc2xmr(destination, amount)
bitmonerod.send(xmr_addr, float(xmr_amount), xmr_pid, 3)
return ('order uuid: '+uuid)
if __name__ == '__main__':
#check if api pubkey is created, if not create it:
if(os.path.isfile('MiniNeroPubKey.py')):
from MiniNeroPubKey import *
try:
MiniNeroPk
except NameError:
MiniNeroSk= PaperWallet.skGen()
MiniNeroPk= HexSigningPubKey(MiniNeroSk)
print("Your new api secret key is:")
print(MiniNeroSk)
print("You should save this in a password manager")
print("Your pubkey will be stored in MiniNeroPubKey.py")
f = open('MiniNeroPubKey.py', 'w')
f.write("MiniNeroPk = \'"+MiniNeroPk+"\'")
print("Your MiniNeroServer PubKey is:")
print(MiniNeroPk)
#Launch Cherry Server
cherrypy.tree.mount(
MiniNeroServer(), '/api/mininero',
{'/':
{'request.dispatch': cherrypy.dispatch.MethodDispatcher()}
}
)
cherrypy.server.socket_host = '0.0.0.0' #run on metal
cherrypy.engine.start()
cherrypy.engine.block()

View file

@ -0,0 +1,16 @@
import MiniNero
import ed25519
import binascii
import PaperWallet
import cherrypy
import os
import time
import bitmonerod
import SimpleXMR2
import SimpleServer
message = "send0d000114545737471em2WCg9QKxRxbo6S3xKF2K4UDvdu6hMc"
message = "send0d0114545747771em2WCg9QKxRxbo6S3xKF2K4UDvdu6hMc"
sec = raw_input("sec?")
print(SimpleServer.Signature(message, sec))

View file

@ -0,0 +1,3 @@
import os
sec = raw_input("wallet pass?")
os.system(" ~/bitmonero/build/release/bin/simplewallet --wallet-file ~/wallet/testwallet1 --password "+sec+" --rpc-bind-port 18082")

View file

@ -0,0 +1,48 @@
import MiniNero
import os
import ed25519
import binascii
import PaperWallet
import json, hmac, hashlib, time, requests
#gets xmr address, xmr amount, and pid for xmr2 order
#inputs are btc destination, and amount in btc
#also will return the order id, so you can track the order
def btc2xmr(dest, amount):
#First create the order..
url = 'https://xmr.to/api/v1/xmr2btc/order_create/'
payload = {'btc_dest_address' : dest, 'btc_amount' : amount}
headers = {'content-type': 'application/json'}
r = requests.post(url, data=json.dumps(payload), headers=headers)
data = json.loads(r.content)
uuid = data['uuid']
print("uuid=", uuid)
#wait a few seconds
print("waiting a few seconds for order to be created")
for i in range(0, 5):
print(".")
time.sleep(1)
#get amount, address, pid
ipStatus = 'https://xmr.to/api/v1/xmr2btc/order_status_query/'
dat = {
'uuid' : uuid
}
r2 = requests.post(ipStatus, data=json.dumps(dat), headers = headers)
#print(r2.text)
data2 = json.loads(r2.content)
xmr_amount = data2['xmr_required_amount']
xmr_addr = data2['xmr_receiving_address']
xmr_pid = data2['xmr_required_payment_id']
print("send ", str(xmr_amount), " xmr to", xmr_addr, "with pid", xmr_pid)
return uuid, xmr_amount, xmr_addr, xmr_pid
#dest = "1em2WCg9QKxRxbo6S3xKF2K4UDvdu6hMc" #your dest address here
#amount = "0.1" #your amount here...
#uuid, xmr_amount, xmr_addr, xmr_pid = btc2xmr(dest, amount)

View file

@ -0,0 +1,22 @@
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
import MiniNero
import PaperWallet
a = 3655169758690262480859172686034352748701568204867449275194046101565641063400
b = 2196281112309589493539510630657048805544016132079821556435431458072258858680
c = 1680308020000391016811131033972168547846809685867129675902005632340344199616
d = 3102886190919558838979092227453570755967767872654511102581747930112259050736
e = a + b + c + d
print(e, e % l)
pk = MiniNero.publicFromSecret(MiniNero.intToHex(e))
pka = MiniNero.publicFromSecret(MiniNero.intToHex(a))
pkb = MiniNero.publicFromSecret(MiniNero.intToHex(b))
pkc = MiniNero.publicFromSecret(MiniNero.intToHex(c))
pkd = MiniNero.publicFromSecret(MiniNero.intToHex(d))
A = MiniNero.addKeys(pka, pkb)
B = MiniNero.addKeys(A, pkc)
C = MiniNero.addKeys(B, pkd)
print(C)
print(pk)

View file

@ -0,0 +1,19 @@
#you += hash(pubkey || index) to both the private scalar and public point
#<tacotime> [02:35:38] so to get priv_i and pub_i
#<tacotime> [02:36:06] priv_i = (priv + hash) mod N
#<tacotime> [02:37:17] pub_i = (pub + scalarbasemult(hash))
import MiniNero
import PaperWallet
sk, vk, pk, pvk, addr, wl, cks = PaperWallet.keysBoth()
print("making keychain")
for i in range(1, 600):
index = MiniNero.intToHex(i)
has = MiniNero.cn_fast_hash(pk + index)
sk1 = MiniNero.sc_add_keys(sk, has)
pk1 = MiniNero.addKeys(pk, MiniNero.scalarmultBase(has))
pk1_check = MiniNero.publicFromSecret(sk1)
print("Check", pk1== pk1_check)
print(sk1)
#print("i, sk, pk", i, sk1, pk1)

View file

@ -0,0 +1,377 @@
#!/usr/bin/python
import sys #for arguments
import MiniNero
import mnemonic
import PaperWallet
import Ecdh
import ASNL
import MLSAG
import MLSAG2
import LLW_Sigs
import RingCT
import Crypto.Random.random as rand
import Translator
import binascii
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
if len(sys.argv) >= 2:
if sys.argv[1] == "id":
Translator.hexToC(MiniNero.identity())
if sys.argv[1] == "smult":
a= "87a61352d86f5cb0e9d227542b6b4870b9a327d082d15ea64e0494b9a896c1ac"
aG = MiniNero.scalarmultBase(a)
print(aG)
print(MiniNero.scalarmultKey(aG, a))
if sys.argv[1] == "add":
#once it's good
A = PaperWallet.pkGen()
A = "75819750158570adc58ad6f932c3704661d6cd8eafd3a14818293a17790fbf71"
B = PaperWallet.pkGen()
B = "5fbc56c82c6e40596c673e301b63e100f08b97723ead425ed38f2b55c7a6454f"
AB = MiniNero.addKeys(A, B)
Translator.hexToC(A)
Translator.hexToC(B)
print(AB)
AAB = MiniNero.addKeys(AB, A)
print("AAB", AAB)
print("hash")
print(MiniNero.sc_reduce_key(MiniNero.cn_fast_hash(A)))
aAbB = MiniNero.addKeys(MiniNero.scalarmultKey(A, A), MiniNero.scalarmultKey(B, B))
print("testing addKeys3")
print(aAbB)
if sys.argv[1] == "rs":
#once it's good
sk = MiniNero.randomScalar()
if sys.argv[1] == "mn":
#checking decoding mnemonic
#seed = "code elope foiled knapsack abyss fishing wayside also joining auburn robot sonic inquest obnoxious pact gave smash itches fierce darted owed queen pool fruit auburn"
seed = "down hairy tattoo ointment austere lush fossil symptoms vary sonic ultimate onslaught pioneer aerial kept linen unnoticed ahead weavers injury buzzer inquest justice nightly symptoms"
seed = "unzip festival cease fences value anchor waking tomorrow ritual hookup guarded antics cease"
sk = MiniNero.recoverSK(seed)
print("sk", sk)
print("addr my monero", MiniNero.getAddr(sk))
if sys.argv[1] == "vk":
#check making viewkey
sk = "86c5616d91c7e7d96ec8220b15a5d441526ecc09f76347a40ab3a67373f8ba03"
sk = "7eb3f0d43fbe9caee69215fbc360f49ce545d0dfae71390d531c9723cb25e904"
vk = MiniNero.getView(sk)
vk = "bb36fe9e852f617093a1634626268b61c5e5e065f503cbdd105877a0a54c3a02"
print(vk)
if sys.argv[1] == "addr":
sk = "b6aafbbb9a6ee768bf292f7ebf977b6a31f51d4ecbf59186dd8367a3012f640f"
sk = "7eb3f0d43fbe9caee69215fbc360f49ce545d0dfae71390d531c9723cb25e904"
sk = "7c404922198b99c08020468c896f13df4f6e2ff1b5ab3c528e014cc9836ce80b"
pk = MiniNero.publicFromSecret(sk)
print("pk", pk)
vk = "9e71628d6db09405a1267550b902299ed5cd004653e52d0a12129a21ab69900d"
vk = "bb36fe9e852f617093a1634626268b61c5e5e065f503cbdd105877a0a54c3a02"
vk = "7c404922198b99c08020468c896f13df4f6e2ff1b5ab3c528e014cc9836ce80b"
vk = "c1c9e45989cc5fbfe828400886c50b4f58da40692d0f6ce6b3d483c4f1bf4b05"
pvk = MiniNero.publicFromSecret(vk)
print("pvk", pvk)
vers = "12"
print(MiniNero.encode_addr(vers, pk, pvk))
if sys.argv[1] == "sp":
a = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"
a = "c8d603858291b23c42695fec0b3db1b7fcb961e63d885a89c6ef70507a0b3204"
a = "7c404922198b99c08020468c896f13df4f6e2ff1b5ab3c528e014cc9836ce80b"
b = MiniNero.publicFromSecret(a)
print(b)
if sys.argv[1] == "crc":
#test vectors
t = "salads wipeout algebra knife awakened jewels uneven tender nearby worry ferry macro uneven"
t = "sadness uneven boil mammal highway zinger enmity inkling coal essential teeming vibrate drunk drowning sulking unnoticed muffin swagger quick musical aquarium equip gather linen quick"
t = "tyrant bailed lynx symptoms winter pirate yanks jagged dawn germs daily left hull pedantic puppy dilute dash adventure pigment nodes hockey yodel across richly adventure"
t = "irony leopard emotion bovine veteran spout weird soccer adventure jeopardy negative rabbits otter boyfriend jackets boil richly apricot cake hydrogen luggage menu muffin sushi menu"
t = "ivory koala decay whole segments cement natural pact omega asylum onslaught pinched jive thumbs nouns pimple baffles uptight okay itself unmask ruthless asked fossil pact"
t = "oneself zodiac aimless october comb egotistic vastness otherwise nobody shelter amidst nexus costume dash rotate evenings zones hope aimless jury onslaught copy excess unzip october"
t = "fifteen eels reorder sneeze fidget inbound onboard tufts lifestyle rounded lilac opened ascend fonts recipe copy android launching unquoted doctor lids reinvest syllabus five sneeze"
t = "vinegar bubble bobsled southern godfather toolbox online hoax error pegs dice pamphlet knapsack erase lottery aside myth surfer exotic wipeout idled pelican cell tiger aside"
t = "aquarium safety null huddle vastness ruined taken hamburger rhythm costume lion cupcake pouch auburn hashing vulture vitals pigment dangerous possible each salads segments fazed vulture"
t = "aquarium safety null huddle vastness ruined taken hamburger rhythm costume lion cupcake pouch auburn hashing vulture vitals pigment dangerous possible each salads segments fazed vulture"
t = raw_input("13 or 25 words?")
a = MiniNero.electrumChecksum(t)
print(a)
if sys.argv[1] == "1224":
#sohuld turn 12 word key to 24
print("tbd")
sk = "536313cc0a88457e3d3e5aadda8d204af20e480416cc522ebd5a67df00ce2503"
print(MiniNero.getAddr(sk))
if sys.argv[1] == "seed":
seed = "3c817618dcbfed122a64e592bb441d73300da9123686224a84e0eab1f075117e";
a = MiniNero.hexToInt(seed)
b = a // l
print(b)
if sys.argv[1] == "HCT":
for i in [1, 12, 123, 1234, 12345, 123456]:
A = MiniNero.publicFromInt(i)
print(i, MiniNero.hashToPoint_ct(A))
if sys.argv[1] == "RingCTSimple":
#see below for ring ct with sliding exponents
exponent = 9
H_ct = RingCT.getHForCT()
print("H", H_ct)
sr, Pr = PaperWallet.skpkGen() #receivers private/ public
se, pe, ss1, ss2 = Ecdh.ecdhGen(Pr) #compute shared secret ss
digits = 32 #in practice it could will be 32 (from .0001 monero to ~400k monero) all other amounts can be represented by full 64 if necessary, otherwise you can use the sliding implementation of RingCT given below.
print("inputs")
a = 10000
Cia, L1a, s2a, sa, ska = RingCT.genRangeProof(10000, digits)
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
ind = 2
for j in range(0, R):
if j > 0:
x.append([None]*N)
P.append([None]*N)
for i in range(0, N):
x[j][i] = PaperWallet.skGen()
P[j][i] = MiniNero.scalarmultBase(x[j][i])
sk[j] = x[j][ind]
print("x", x)
II, cc, ss = MLSAG.MLSAG_Sign(P, sk, ind)
print("Sig verified?", MLSAG.MLSAG_Ver(P, II, cc, ss) )
if sys.argv[1] == "MLSAG2":
#below is example usage. Uncomment each line for testing
rows = 3 #cols
cols = 3 #rows
ind = 1
x = MLSAG2.skmGen(rows, cols)
sk = x[ind]
P = MLSAG2.keyMatrix(rows, cols)
for i in range(0, cols):
P[i] = MLSAG2.vScalarMultBase(x[i])
II, cc, ss = MLSAG2.MLSAG_Gen(P, sk, ind)
print("I", II)
print("c0", cc)
print("s", ss)
print("Sig verified?", MLSAG2.MLSAG_Ver(P, II, cc, ss) )
if sys.argv[1]== "MLSAGc":
P = [["4a199991d80915f99870b702fb6b3fa7b127853c4ed12ac2bb071534b9b5dee6","86e2c2ec0262c465749fdb1940de954d87d1e6b96beda093bc185f329e157c53","e9e83e74299bd3cdad4c87c6548dba859680000740660d1f783486d4cafef79f"],["78656dbba0fdfd14fc99b4da8b73c81314b9e65eeaa4eac510ca4dd28bae63a0","987f7b1b498e6ec25ad2ce304300388396a374721a24602b16905eeeb9a42fb0","b1a9c583747a8815fa7a80452efb4f93042dc64db08b3d2f7ac5016ea2b882eb"],["d3ef77673ee441b2ca3b1f9e7f628df9f6306d89d8c5155c3c6ee4c9f5f51408","5423f77332aa6a015ddc70a82e27fe52c68ab47e08b5c07d03641194de4ea1fb","ec564efa1511f73f91649d942fff0921763e4be37ee114036bd584f7a8fb9fd9"]]
cc = "cd12f7147c6c01dee58be3338244b6f386806020e2d266a6aac68a4ab4bfb28b"
II = ["352d19bc0ab8b45241dc23c27c4598791d4e23cd370198aea8eee8c7b5eb7b1d","8e2bca011d5b1fadde79dee44329545ca903b7bd299c4719e7593ad096e96141","5c6fad47d9ec734dab1139c40d4f11482e3d1f76585643520697a17f687a5962"]
ss = [["e26f3115a50a2a25f1ec9582a4f4058f7f5c1b3f467cc38b0e882df7f93d6d0a","6b20f43b1f3c56ff3070b1a9a4612c808c35787a26243f5c046e283ff1b68f09","5091182154ad97d33c8210954b0570ccf95e8bedc5c6c193bde7d562bd9dc20a"],["ac297d01a6923e1c79d0fff82ecbfe0ae6ce515ef2b0dbc7e6b2f6542b99a404","c5371c10d7e7071ce3b3016db65bb29194e91a09cf428237fcf4037de74b5d03","a357b1453acd01fa101593994f60014f8ee7657921690bb4dfb0cfc41ef20802"],["a4a6ceb8454754ad32c987bcc56a03432155b47315f8805a3577a0470b0b330d","0ec6b71c2c6ba34d34bc3ea27e6813091fb3a90dc261a77fc9f46068bb1a3b09","41417b047353352e145fd3e65fe1e51e95081a64e9fda561060167e132c5e602"]]
rows = 3 #cols
cols = c #rows
print("I", II)
print("c0", cc)
print("s", ss)
print("Sig verified?", MLSAG2.MLSAG_Ver(P, II, cc, ss) )
if sys.argv[1] == "LLW":
#below is example usage
N = 3
x = [None]*N
P = [None]*N
HP = [None]*N
for i in range(0, N):
x[i] = PaperWallet.skGen()
P[i] = MiniNero.scalarmultBase(x[i])
print("x", x)
pjoin = ''.join(P)
ind = 0
II, cc, ss = LLW_Sigs.LLW_Sig(P[:], x[ind], ind )
print("Sig verified?", LLW_Sigs.LLW_Ver(P[:], II, cc, ss[:]) )
if sys.argv[1] == "Ecdh":
x1, pk1 = PaperWallet.skpkGen() #receiver secret key / public key
ephem, ephempub, ss = Ecdh.ecdhGen(pk1) #ephempub is public key to create shared key
ss2 = Ecdh.ecdhRetrieve(x1, ephempub)
print "shared secret from sender: "
print ss
print "shared secret calculated by receiver: "
print ss2
if sys.argv[1] == "Schnorr":
#test basic schnorr
mes = "a very long test message asdflgkjnasdbfblkjnsdfblkjnsdfbklmnsdfbkl;jnsdfblkjsndfgblkjnserfvliksjndcmblkjxncvblikjhnwersfiodusjbsndlfigb7uvy3qo890eruiyghsblfduihjbo 9sruifjtyghbnqliownfghjbdlfkjvnb"
sec = "7c404922198b99c08020468c896f13df4f6e2ff1b5ab3c528e014cc9836ce80b"
pub = MiniNero.scalarmultBase(sec)
r, c = ASNL.GenSchnorr(mes, sec, pub)
print("sig verifies?",ASNL.VerSchnorr(mes, pub, r, c))
print("sig verifies?",ASNL.VerSchnorr(mes, pub, r, PaperWallet.skGen()))
if sys.argv[1] == "SchnorrNL":
#test schnorr nonlinkable
x, P2 = PaperWallet.skpkGen()
P1 = PaperWallet.pkGen()
L1, s1, s2 = ASNL.GenSchnorrNonLinkable(x, P1, P2, 1)
ASNL.VerSchnorrNonLinkable(P1, P2, L1, s1, s2)
if sys.argv[1] == "ASNL":
#below tests ASNL code
N = 10
x = [None] * N
P1 = [None] * N
P2 = [None] * N
indi = [None] * N
for j in range(0, N):
indi[j] = rand.getrandbits(1)
x[j] = PaperWallet.skGen()
if indi[j] == 0:
P1[j] = MiniNero.scalarmultBase(x[j])
P2[j] = PaperWallet.pkGen()
else:
P2[j] = MiniNero.scalarmultBase(x[j])
P1[j] = PaperWallet.pkGen()
L1, s2, s = ASNL.GenASNL(x, P1, P2, indi)
ASNL.VerASNL(P1, P2, L1, s2, s)
if sys.argv[1] == "brief":
#shows compatibility with Ref10 (c.f. with sh runtest.sh in brief directory
sec = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"
P = MiniNero.scalarmultBase(sec)
print(P)
if sys.argv[1] == "RingCT":
#global stuff, i.e. inputs
exponent = 9
H_ct = RingCT.getHForCT()
sr, Pr = PaperWallet.skpkGen() #receivers private/ public
digits = 14 #in practice you can either specify it as part of the protocol, or allow a sliding value
a = 10
b = 7
c = 3
P2 = PaperWallet.pkGen()
C2 = PaperWallet.pkGen() #some random commitment grabbed from the blockchain
x, P1 = PaperWallet.skpkGen()
ind = 0
#From the previous transaction
print("inputs")
Ca, Cia, L1a, s2a, sa, ska = RingCT.genRangeProof(a, digits)
#Actions performed by sender
se, pe, ss1, ss2 = Ecdh.ecdhGen(Pr) #compute shared secret ss
print("outputs")
Cb, Cib, L1b, s2b, sb, skb = RingCT.genRangeProof(b, digits)
Cc, Cic, L1c, s2c, sc, skc = RingCT.genRangeProof(c, digits)
print("verifying range proofs of outputs")
RingCT.verRangeProof(Cib, L1b, s2b, sb) #only need these for outputs (the input above is assumed in a previous transaction..
RingCT.verRangeProof(Cic, L1c, s2c, sc)
pk, II, cc, ssVal = RingCT.genRCTSig([x], [ska], [skb, skc], [P1, P2], [[Ca], [C2]], [Cb, Cc], [[exponent],[3]], [exponent, exponent], 0)
#Actions performed by the Miner
print("Sig verified?", MLSAG.MLSAG_Ver(pk, II, cc, ssVal) )
#Actions performed by receiver(s)
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] == "ctest":
sk, Pk= PaperWallet.skpkGen()
print("running scalarmult base on ", sk, Pk)
Translator.t_header()
Translator.hexToC(sk, "sec")
Translator.t_scalarmultBase("sec", "pub")
Translator.t_footer()
if sys.argv[1] == "chash":
#pk = "ff33f4df1f8f44bfed3572134814f83c890495bd4714a0aaff0e0239c1acc927"
sk, Pk= PaperWallet.skpkGen()
#h = MiniNero.cn_fast_hash(pk)
#print("pk", pk)
#Translator.hexToC(pk, "pub")
#print("hash", h)
Translator.t_header()
Translator.hexToC(sk, "sec")
Translator.t_scalarmultBase("sec", "pub")
Translator.t_cn_fast_hash("pub", "h")
Translator.t_footer()
if sys.argv[1] == "cSchnorr":
prefix = "a very long test message asdflgkjnasdbfblkjnsdfblkjnsdfbklmnsdfbkl;jnsdfblkjsndfgblkjnserfvliksjndcmblkjxncvblikjhnwersfiodusjbsndlfigb7uvy3qo890eruiyghsblfduihjbo 9sruifjtyghbnqliownfghjbdlfkjvnb"
hash_prefix = MiniNero.cn_fast_hash(binascii.hexlify(prefix))
h="247a9b60e8a31c18bfab9f6bf7b5079bc8c1955ea6726ea3f2bc38a3ec1bc658"
pubb="ff33f4df1f8f44bfed3572134814f83c890495bd4714a0aaff0e0239c1acc927"
sec="9d5f81503e5280cd8fdcd12c94bea81bdf4c2f87ebc0992ab177fba51db92c0a"
r, c = ASNL.GenSchnorr(h,pubb, sec, PaperWallet.skGen())
Translator.sigToC(r, c)
print("verd?", ASNL.VerSchnorr(h, pubb, r, c))
if sys.argv[1] == "data":
skv = ["ae5934fe1e8065ec19afc80f2f06fc3f36730405a022813e2b18dc9da929da02", "2a9f99b0313157ba599bde727e04d6bfe87163f1d7dc93a352b1a648d7178205", "f0fb4504b06785caac17f4c554526685eed71d21b9b542f50c6e396b6152a403", "e5f7c934aa59c2ea21efeb4695d09bb95402d0dcc92d5bbec59eb1fc5912cf0f", "795f05824fb9e4a0808a523ecc9fefcb9e563e152d9b101224cb18169d3a4a05"]
pkv = MLSAG2.vScalarMultBase(skv)
print(pkv)
if sys.argv[1] == "addKeys":
a, A = ('13e467e9c0034e6878af5c801a81ee0543b1096b5ab01356b349cc3235cd1909', 'a50e5e751a9906f9ff086c734591d0ee87be6ca58fe7208b8e070e54d2eda0da')
b, B = ('cd43ec6b80dd5ea2668e141fc6dc1191258b5eb58bf7dbef9e647aca3ba09707', '4f31e64eb9017ac02c6313294d0554d4532fbd6ffd15bc175422060867ab33f4')
Translator.hexToC(a)
Translator.hexToC(b)
print(MiniNero.addKeys1(a, b, B))
print(MiniNero.addKeys2(a, A, b, B))
if sys.argv[1] == "bighash":
from bighash import *
print(MiniNero.cn_fast_hash(a))
b = "d99e55005f1736e5d843dd11ce80e3e989f3eea52a42e14f6c541620568569ed"
if sys.argv[1] == "ch":
a = "18a5f3cf50ae2207d8ccd70179a13b4fc339d0cd6d9138c6d764f8e4cef8f006c87b1367fef3f02ed5ffd42a7ea212c2b8899af3af8f4b1e34139e1e390f3af1"
print(MiniNero.cn_fast_hash(a))
if sys.argv[1] == "fastbin":
b = "0123456789abcdef"
c = MiniNero.hexToInt(b)
c = 6000
print(b, c)
Translator.hexToC(b)
b = RingCT.binary(c, 64)
b2 = ''.join([str(a) for a in b])
print(b2)
if sys.argv[1] == "HPow2":
A = MiniNero.publicFromInt(1)
HPow2 = MiniNero.hashToPoint_ct(A)
two = MiniNero.intToHex(2)
for j in range(1, 64):
key = HPow2
while len(key) < 64:
key = key + "0"
k2 = [key[i:i+2] for i in range(0, len(key), 2)]
ar = "{0x"+(", 0x".join(k2))+"}, "
print(ar)
HPow2 = MiniNero.scalarmultKey(HPow2, two)
print("};")
if sys.argv[1] == "h2":
A = MiniNero.publicFromInt(1)
H = MiniNero.hashToPoint_ct(A)
print(MiniNero.addKeys(H, H))
print(MiniNero.scalarmultKey(H, MiniNero.intToHex(2)))

View file

@ -0,0 +1,54 @@
#the goal with this is to automagically Convert MiniNero Code to ref10 C equivalent
import MiniNero
def t_header():
print("#include <stdlib.h>")
print("#include <stdio.h>")
print("#include <string.h>")
print("#include <stdint.h>")
print("#include \"crypto-ops.h\"")
print("#include \"crypto.h\"\n\n")
print("#include \"keccak.h\"")
print("#define BYTES 64\n\n")
print("int main(int argc, char *argv[]) {\n\n")
def t_footer():
print("return 0;\n}\n\n")
def hexToC(key):
while len(key) < 64:
key = key + "0"
k2 = [key[i:i+2] for i in range(0, len(key), 2)]
ar = "{{0x"+(", 0x".join(k2))+"}}"
print(ar)
def sigToC(r, c):
r2 = [r[i:i+2] for i in range(0, len(r), 2)]
ar = "{0x"+(", 0x".join(r2))+"}"
c2 = [c[i:i+2] for i in range(0, len(c), 2)]
ac = "{0x"+(", 0x".join(c2))+"}"
print("signature sig = {"+ac+", "+ar+"};\n\n")
def t_scalarmultBase(name_in, name_out):
print("//Running scalarmult Base on "+name_in)
print("ge_p3 point;")
print("ge_scalarmult_base(&point, "+name_in+");")
print("unsigned char "+name_out+"[32];")
print("ge_p3_tobytes("+name_out+", &point);\n\n")
def t_cn_fast_hash(name_in, name_out):
print("\n//running cn_fast_hash on "+name_in)
print("uint8_t md2[32];")
print("unsigned char "+name_out+"[32] = {0};")
print("int j = 0;")
print("keccak((uint8_t *) "+name_in+", 32, md2, 32);")
print("for (j= 0 ; j < 32 ; j++) {")
print("h[j] = (unsigned char)md2[j];")
print("}")
print("printf(\"\\nhash:\\n\");")
print("for (j = 0 ; j < 32 ; j++) {")
print("printf(\"%02x\", "+name_out+"[j]);")
print("}")

View file

@ -0,0 +1,179 @@
#The following code is taken for the most part from
#https://github.com/moneroexamples/python-json-rpc.git
#I've slightly modified it to fit the cherry py server better
import requests
import json
import os
import binascii
def send(destination_address, amount, payment_id, mixin):
# simple wallet is running on the localhost and port of 18082
url = "http://localhost:18082/json_rpc"
# standard json header
headers = {'content-type': 'application/json'}
# cryptonote amount format is different then
# that normally used by people.
# thus the float amount must be changed to
# something that cryptonote understands
int_amount = int(get_amount(amount))
# just to make sure that amount->coversion->back
# gives the same amount as in the initial number
assert amount == float(get_money(str(int_amount))), "Amount conversion failed"
# send specified xmr amount to the given destination_address
recipents = [{"address": destination_address,
"amount": int_amount}]
# simplewallet' procedure/method to call
rpc_input = {
"method": "transfer",
"params": {"destinations": recipents,
"mixin": mixin,
"payment_id" : payment_id}
}
# add standard rpc values
rpc_input.update({"jsonrpc": "2.0", "id": "0"})
# execute the rpc request
response = requests.post(
url,
data=json.dumps(rpc_input),
headers=headers)
# print the payment_id
print("#payment_id: ", payment_id)
# pretty print json output
print(json.dumps(response.json(), indent=4))
def get_amount(amount):
"""encode amount (float number) to the cryptonote format. Hope its correct.
Based on C++ code:
https://github.com/monero-project/bitmonero/blob/master/src/cryptonote_core/cryptonote_format_utils.cpp#L211
"""
CRYPTONOTE_DISPLAY_DECIMAL_POINT = 12
str_amount = str(amount)
fraction_size = 0
if '.' in str_amount:
point_index = str_amount.index('.')
fraction_size = len(str_amount) - point_index - 1
while fraction_size < CRYPTONOTE_DISPLAY_DECIMAL_POINT and '0' == str_amount[-1]:
print(44)
str_amount = str_amount[:-1]
fraction_size = fraction_size - 1
if CRYPTONOTE_DISPLAY_DECIMAL_POINT < fraction_size:
return False
str_amount = str_amount[:point_index] + str_amount[point_index+1:]
if not str_amount:
return False
if fraction_size < CRYPTONOTE_DISPLAY_DECIMAL_POINT:
str_amount = str_amount + '0'*(CRYPTONOTE_DISPLAY_DECIMAL_POINT - fraction_size)
return str_amount
def get_money(amount):
"""decode cryptonote amount format to user friendly format. Hope its correct.
Based on C++ code:
https://github.com/monero-project/bitmonero/blob/master/src/cryptonote_core/cryptonote_format_utils.cpp#L751
"""
CRYPTONOTE_DISPLAY_DECIMAL_POINT = 12
s = amount
if len(s) < CRYPTONOTE_DISPLAY_DECIMAL_POINT + 1:
# add some trailing zeros, if needed, to have constant width
s = '0' * (CRYPTONOTE_DISPLAY_DECIMAL_POINT + 1 - len(s)) + s
idx = len(s) - CRYPTONOTE_DISPLAY_DECIMAL_POINT
s = s[0:idx] + "." + s[idx:]
return s
def balance():
# simple wallet is running on the localhost and port of 18082
url = "http://localhost:18082/json_rpc"
# standard json header
headers = {'content-type': 'application/json'}
# simplewallet' procedure/method to call
rpc_input = {
"method": "getbalance"
}
# add standard rpc values
rpc_input.update({"jsonrpc": "2.0", "id": "0"})
# execute the rpc request
response = requests.post(
url,
data=json.dumps(rpc_input),
headers=headers)
# amounts in cryptonote are encoded in a way which is convenient
# for a computer, not a user. Thus, its better need to recode them
# to something user friendly, before displaying them.
#
# For examples:
# 4760000000000 is 4.76
# 80000000000 is 0.08
#
# In example 3 "Basic example 3: get incoming transfers" it is
# shown how to convert cryptonote values to user friendly format.
# pretty print json output
print(json.dumps(response.json(), indent=4))
def myAddress():
# simple wallet is running on the localhost and port of 18082
url = "http://localhost:18082/json_rpc"
# standard json header
headers = {'content-type': 'application/json'}
"""return the wallet's address"""
rpc_input = {
"method": "getaddress"
}
response = do_rpc(url, headers, rpc_input)
return response.json()
def do_rpc(url,headers, rpc_input):
"""does the rpc calls"""
# add standard rpc values
rpc_input.update({"jsonrpc": "2.0", "id": "0"})
# execute the rpc requrest
response = requests.post(
url,
data=json.dumps(rpc_input),
headers=headers)
return response

View file

@ -0,0 +1,17 @@
--for quick conversion of the MiniNero python code to c++
--
if #arg > 0 then
class = string.lower(arg[1]) --asdf
object = arg[1] --Asdf
deff = string.upper(arg[1]) --ASDF
hfile = io.input("TemplateHead"):read("*a")
cppfile = io.input("TemplateBody"):read("*a")
hfile = string.gsub(hfile, "asdf", class)
hfile = string.gsub(hfile, "Asdf", object)
hfile = string.gsub(hfile, "ASDF", deff)
cppfile = string.gsub(cppfile, "asdf", class)
cppfile = string.gsub(cppfile, "Asdf", object)
cppfile = string.gsub(cppfile, "ASDF", deff)
io.output(object..".h"):write(hfile)
io.output(object..".cpp"):write(cppfile)
end

View file

@ -0,0 +1,4 @@
gtags.exe
mingw32-make.exe clean
mingw32-make.exe
a.exe > .results

View file

@ -0,0 +1,4 @@
gtags.exe
make clean
make
./a.exe

View file

@ -0,0 +1,3 @@
rm.exe a.exe
g++ bits.cpp
./a.exe

View file

@ -0,0 +1 @@
%1

View file

@ -0,0 +1,132 @@
#!/usr/bin/python
#Some code to do the same thing as btcproof (since I think there may be an error in their file hashing?)
#some of this code is taken from KeyUtils.py on a random github, so if you made that, then thanks
import sys
import ecdsa
import ecdsa.der
import ecdsa.util
import hashlib
import os
import re
import struct
import webbrowser #for qr code of address
b58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
VERSION = 0x00
def base58encode(n):
result = ''
while n > 0:
result = b58[n%58] + result
n /= 58
return result
def base256decode(s):
result = 0
for c in s:
result = result * 256 + ord(c)
return result
def countLeadingChars(s, ch):
count = 0
for c in s:
if c == ch:
count += 1
else:
break
return count
# https://en.bitcoin.it/wiki/Base58Check_encoding
def base58CheckEncode(version, payload):
s = chr(version) + payload #concat version
checksum = hashlib.sha256(hashlib.sha256(s).digest()).digest()[0:4]
print("checksum", checksum)
result = s + checksum #concat checksum to end
leadingZeros = countLeadingChars(result, '\0')
#return base58encode(base256decode(result))
return '1' * leadingZeros + base58encode(base256decode(result))
def privateKeyToWif(key_hex):
return base58CheckEncode(VERSION, key_hex.decode('hex'))
def privateKeyToPublicKey(s):
sk = ecdsa.SigningKey.from_string(s.decode('hex'), curve=ecdsa.SECP256k1)
vk = sk.verifying_key
return ('\04' + sk.verifying_key.to_string()).encode('hex')
def pubKeyToAddr(s):
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(hashlib.sha256(s.decode('hex')).digest())
return base58CheckEncode(0, ripemd160.digest())
def keyToAddr(s):
return pubKeyToAddr(privateKeyToPublicKey(s))
## below tto create digest of file, result should not vary with blocksize
BLOCKSIZE = 2 **10
def sha256OfFile(filepath):
sha = hashlib.sha256()
with open(filepath, 'rb') as f:
while True:
block = f.read(BLOCKSIZE)
if len(block) < BLOCKSIZE:
print(len(block))
block = block[:-1]
if not block: break
sha.update(block)
return sha.hexdigest()
##proofs, c.f.
#https://www.btproof.com/technical.html
# hash = SHA256(DATA) // or the supplied hash
#vhash = CONCAT(VERSION_BYTE, RIPEMD160(hash)) // VERSION_BYTE is 0x00 for main net
#address = BASE58(CONCAT(vhash, SHA256(SHA256(vhash))[0..3]))
def btcProofOfFile(fi):
has = sha256OfFile(fi)
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(has)
address = base58CheckEncode(0, ripemd160.digest())
return address
def btcProofOfString(strin):
sha = hashlib.sha256()
sha.update(strin)
has = sha.digest()
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(has)
address = base58CheckEncode(0, ripemd160.digest())
return address
# Generate a random private key
#private_key = os.urandom(32).encode('hex')
#address = base58CheckEncode(version, payload)
#this works (check sha test vectors at http://www.di-mgt.com.au/sha_testvectors.html) indicating I am hashing the file correctly
#print(sha256OfFile("a.txt"))
#print("should be: cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0")
#this works
#print("address for abc")
#print(btcProofOfString("abc"))
#this does not agree with btcproof.com, indicating they are hashing file wrong
#print("address for a.txt")
#print(btcProofOfFile("a.txt"))
#print("bitcoin:"+btcProofOfFile(sys.argv[1])+"?amount=0.0001")
a = btcProofOfFile(sys.argv[1])
print(a)
#bitcoin:1PZmMahjbfsTy6DsaRyfStzoWTPppWwDnZ?amount=0.1
#url = "https://chart.googleapis.com/chart?chs=250x250&cht=qr&chl="+a
url2 = "https://blockchain.info/address/"+a
#print(url)
print(url2)
#webbrowser.open(url)
webbrowser.open(url2)

View file

@ -0,0 +1,129 @@
#ed25519.cr.yp.to/python/ed25519.py
import hashlib
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
def H(m):
return hashlib.sha512(m).digest()
def expmod(b,e,m):
if e == 0: return 1
t = expmod(b,e/2,m)**2 % m
if e & 1: t = (t*b) % m
return t
def inv(x):
return expmod(x,q-2,q)
d = -121665 * inv(121666)
I = expmod(2,(q-1)/4,q)
def xrecover(y):
xx = (y*y-1) * inv(d*y*y+1)
x = expmod(xx,(q+3)/8,q)
if (x*x - xx) % q != 0: x = (x*I) % q
if x % 2 != 0: x = q-x
return x
By = 4 * inv(5)
Bx = xrecover(By)
B = [Bx % q,By % q]
def edwards(P,Q):
x1 = P[0]
y1 = P[1]
x2 = Q[0]
y2 = Q[1]
x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2)
y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2)
return [x3 % q,y3 % q]
def edwards_Minus(P, Q): #added
x1 = P[0]
y1 = P[1]
x2 = (-1 * Q[0]) % q
y2 = Q[1]
x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2)
y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2)
return [x3 % q,y3 % q]
def scalarmult(P,e):
if e == 0: return [0,1]
Q = scalarmult(P,e/2)
Q = edwards(Q,Q)
if e & 1: Q = edwards(Q,P)
return Q
#added scalarmultbase
def scalarmultbase(e):
if e == 0: return [0,1]
Q = scalarmult(B,e/2)
Q = edwards(Q,Q)
if e & 1: Q = edwards(Q,B)
return Q
def encodeint(y):
bits = [(y >> i) & 1 for i in range(b)]
return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
def encodepoint(P):
x = P[0]
y = P[1]
bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1]
return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
def bit(h,i):
return (ord(h[i/8]) >> (i%8)) & 1
def publickey(sk):
h = H(sk)
a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
A = scalarmult(B,a)
return encodepoint(A)
def Hint(m):
h = H(m)
return sum(2**i * bit(h,i) for i in range(2*b))
def signature(m,sk,pk):
h = H(sk)
a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m)
R = scalarmult(B,r)
S = (r + Hint(encodepoint(R) + pk + m) * a) % l
return encodepoint(R) + encodeint(S)
def isoncurve(P):
x = P[0]
y = P[1]
return (-x*x + y*y - 1 - d*x*x*y*y) % q == 0
def decodeint(s):
return sum(2**i * bit(s,i) for i in range(0,b))
def decodepoint(s):
y = sum(2**i * bit(s,i) for i in range(0,b-1))
x = xrecover(y)
if x & 1 != bit(s,b-1): x = q-x
P = [x,y]
if not isoncurve(P): raise Exception("decoding point that is not on curve")
return P
def checkvalid(s,m,pk):
if len(s) != b/4:
raise Exception("signature length is wrong")
return False
if len(pk) != b/8:
raise Exception("public-key length is wrong")
return False
R = decodepoint(s[0:b/8])
A = decodepoint(pk)
S = decodeint(s[b/8:b/4])
h = Hint(encodepoint(R) + pk + m)
if scalarmult(B,S) != edwards(R,scalarmult(A,h)):
raise Exception("signature does not pass verification")
return False
return True

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
> python btcProof.py mrl_notes0.4_copy.pdf
779
0
('checksum', '\xd3DC~')
15jVTLpbuU6cH39aqDxWWSb1UnKS2J7MbT
https://blockchain.info/address/15jVTLpbuU6cH39aqDxWWSb1UnKS2J7MbT

Binary file not shown.

View file

@ -0,0 +1,8 @@
15
0
('checksum', '\xe2\xee\x11O')
bitcoin:12axbjZYAasGTnC9ADsaQfmAjEBYpWf82z?amount=0.0001
15
0
('checksum', '\xe2\xee\x11O')
12axbjZYAasGTnC9ADsaQfmAjEBYpWf82z

Binary file not shown.

View file

@ -0,0 +1 @@
import MiniNero

View file

@ -0,0 +1,708 @@
########################################################################
# MiniNero.py
#A miniature, commented
#port of CryptoNote and
#Monero:
# crypto.cpp / crypto-ops.cpp
#
#Using Bernstein's ed25519.py for the curve stuff.
#The main point is to have a model what's happening in CryptoNote
# -Shen.Noether
#
#Note: The ring image function seems
# to take a lot of memory to run
# it will throw strange errors if
# your computer doesn't have
# enough
#Note2:
# As of yet, slightly incompatible, although mathematically equivalent.
# The discrepancies are some differences in packing and hashing.
#
# To the extent possible under law, the implementer has waived all copyright
# and related or neighboring rights to the source code in this file.
# http://creativecommons.org/publicdomain/zero/1.0/
#
#The parts of code from Bernstein(?)'s library possibly has it's own license
# which you can dig up from http://cr.yp.to/djb.html
########################################################################
import hashlib
import struct
import base64
import binascii
import sys
from Crypto.Util import number
import Crypto.Random.random as rand
import Keccak
from collections import namedtuple
import copy
KEK=Keccak.Keccak(1600)
CURVE_P = (2**255 - 19)
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
BASEPOINT = "0900000000000000000000000000000000000000000000000000000000000000"
#####################################
#Bernstein(?) Eddie Library in python
#####################################
def H(m):
return hashlib.sha512(m).digest()
def expmod(b,e,m):
if e == 0: return 1
t = expmod(b,e/2,m)**2 % m
if e & 1: t = (t*b) % m
return t
def inv(x):
return expmod(x,q-2,q)
d = -121665 * inv(121666)
I = expmod(2,(q-1)/4,q)
def xrecover(y):
xx = (y*y-1) * inv(d*y*y+1)
x = expmod(xx,(q+3)/8,q)
if (x*x - xx) % q != 0: x = (x*I) % q
if x % 2 != 0: x = q-x
return x
By = 4 * inv(5)
Bx = xrecover(By)
B = [Bx % q,By % q]
def edwards(P,Q):
x1 = P[0]
y1 = P[1]
x2 = Q[0]
y2 = Q[1]
x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2)
y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2)
return [x3 % q,y3 % q]
def scalarmult(P, e):
if e == 0: return [0,1]
Q = scalarmult(P,e/2)
Q = edwards(Q,Q)
if e & 1: Q = edwards(Q,P)
return Q
def encodeint(y):
bits = [(y >> i) & 1 for i in range(b)]
return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
def encodepoint(P):
x = P[0]
y = P[1]
bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1]
return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
def bit(h,i):
return (ord(h[i/8]) >> (i%8)) & 1
def public_key(sk):
A = scalarmult(B,sk)
return encodepoint(A)
def Hint(m):
h = H(m)
return sum(2**i * bit(h,i) for i in range(2*b))
def signature(m,sk,pk):
h = H(sk)
a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m)
R = scalarmult(B,r)
S = (r + Hint(encodepoint(R) + pk + m) * a) % l
return encodepoint(R) + encodeint(S)
def isoncurve(P):
x = P[0]
y = P[1]
return (-x*x + y*y - 1 - d*x*x*y*y) % q == 0
def decodeint(s):
return sum(2**i * bit(s,i) for i in range(0,b))
def decodepoint(s):
y = sum(2**i * bit(s,i) for i in range(0,b-1))
x = xrecover(y)
if x & 1 != bit(s,b-1): x = q-x
P = [x,y]
if not isoncurve(P): raise Exception("decoding point that is not on curve")
return P
def checkvalid(s,m,pk):
if len(s) != b/4: raise Exception("signature length is wrong")
if len(pk) != b/8: raise Exception("public-key length is wrong")
R = decodepoint(s[0:b/8])
A = decodepoint(pk)
S = decodeint(s[b/8:b/4])
h = Hint(encodepoint(R) + pk + m)
if scalarmult(B,S) != edwards(R,scalarmult(A,h)):
raise Exception("signature does not pass verification")
#################################
#curve stuff,
#mostly from https://github.com/monero-project/bitmonero/blob/1b8a68f6c1abcf481652c2cfd87300a128e3eb32/src/crypto/crypto-ops.c
#partial reference for fe things https://godoc.org/github.com/agl/ed25519/edwards25519
#note ge is the edwards version of the curve
#fe is the monty version of the curve
#################################
#NOT USED IN MININERO - Use ge_scalarmult_base
def ge_fromfe_frombytesvartime(s):
#inputs something s (I assume in bytes)
#inputs into montgomery form (fe)
#then, turns it into edwards form (ge)
#then r is the edwards curve point r->
#reference 1: http://crypto.stackexchange.com/questions/9536/converting-ed25519-public-key-to-a-curve25519-public-key?rq=1
#reference 2: https://github.com/orlp/ed25519/blob/master/src/key_exchange.c
#best reference https://www.imperialviolet.org/2013/12/25/elligator.html
#the point of this function is to return a ge_p2 from an int s
#whereas, the similar function ge_frombytes_vartime returns a gep3
return
def ge_double_scalarmult_base_vartime(aa, AA, bb):
#a very nice comment in the CN code for this one!
#r = a * A + b * B
#where a = a[0]+256*a[1]+...+256^31 a[31].
#and b = b[0]+256*b[1]+...+256^31 b[31].
#B is the Ed25519 base point (x,4/5) with x positive.
#cf also https://godoc.org/github.com/agl/ed25519/edwards25519
tmpa = ge_scalarmult(aa, AA)
tmpb = ge_scalarmult(bb, BASEPOINT)
return toHex(edwards(toPoint(tmpa), toPoint(tmpb)))
def ge_double_scalarmult_vartime(aa, AA, bb, BB):
#a very nice comment in the CN code for this one!
#r = a * A + b * B
#where a = a[0]+256*a[1]+...+256^31 a[31].
#and b = b[0]+256*b[1]+...+256^31 b[31].
#B is the Ed25519 base point (x,4/5) with x positive.
#cf also https://godoc.org/github.com/agl/ed25519/edwards25519
tmpa = ge_scalarmult(aa, AA)
tmpb = ge_scalarmult(bb, BB)
return toHex(edwards(toPoint(tmpa), toPoint(tmpb)))
def toPoint(pubkey):
#turns hex key into x, y field coords
return decodepoint(pubkey.decode("hex"))
def toHex(point):
#turns point into pubkey (reverse of toPoint)
return encodepoint(point).encode("hex")
def ge_scalarmult(a, A):
#so I guess given any point A, and an integer a, this computes aA
#so the seecond arguement is definitely an EC point
# from http://cr.yp.to/highspeed/naclcrypto-20090310.pdf
# "Alice's secret key a is a uniform random 32-byte string then
#clampC(a) is a uniform random Curve25519 secret key
#i.e. n, where n/8 is a uniform random integer between
#2^251 and 2^252-1
#Alice's public key is n/Q compressed to the x-coordinate
#so that means, ge_scalarmult is not actually doing scalar mult
#clamping makes the secret be between 2^251 and 2^252
#and should really be done
#print(toPoint(A))
return encodepoint(scalarmult(toPoint(A), a)).encode("hex") # now using the eddie function
def ge_scalarmult_base(a):
#in this function in the original code, they've assumed it's already clamped ...
#c.f. also https://godoc.org/github.com/agl/ed25519/edwards25519
#it will return h = a*B, where B is ed25519 bp (x,4/5)
#and a = a[0] + 256a[1] + ... + 256^31 a[31]
#it assumes that a[31 <= 127 already
return ge_scalarmult(8*a, BASEPOINT)
#NOT USED IN MININERO - use ge_scalarmult_base
def ge_frombytes_vartime(key):
#https://www.imperialviolet.org/2013/12/25/elligator.html
#basically it takes some bytes of data
#converts to a point on the edwards curve
#if the bytes aren't on the curve
#also does some checking on the numbers
#ex. your secret key has to be at least >=4294967277
#also it rejects certain curve points, i.e. "if x = 0, sign must be positive
return 0
#NOT USED IN MININERO - unecessary as all operations are from hex
def ge_p1p1_to_p2(p):
#there are two ways of representing the points
##http://code.metager.de/source/xref/lib/nacl/20110221/crypto_sign/edwards25519sha512batch/ref/ge25519.c
#http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
return
#NOT USED IN MININERO -unnecessary as operations are from hex
def ge_p2_dbl():
#basically it doubles a point and doubles it
#c.f. Explicit Formulas for Doubling (towards bottom)
#Explicit formulas for doubling
#http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
return
#NOT USED IN MININERO - unnecessary as operations are from hex
def ge_p3_to_p2():
#basically, it copies a point in 3 coordinates to another point
#c.f. Explicit Formulas for Doubling (towards bottom)
#Explicit formulas for doubling
#http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
return
def ge_mul8(P):
#ok, the point of this is to double three times
#and the point is that the ge_p2_dbl returns a point in the p1p1 form
#so that's why have to convert it first and then double
return ge_scalarmult(8, P)
def sc_reduce(s):
#inputs a 64 byte int and outputs the lowest 32 bytes
#used by hash_to_scalar, which turns cn_fast_hash to number..
r = longToHex(s)
r = r[64::]
#print("before mod p", r)
return hexToLong(r) % CURVE_P
def sc_reduce32(data):
#ok, the code here is exactly the same as sc_reduce
#(which is default lib sodium)
#except it is assumed that your input
#s is alread in the form:
# s[0]+256*s[1]+...+256^31*s[31] = s
#and the rest is just reducing mod l
#so basically take a 32 byte input, and reduce modulo the prime
return data % CURVE_P
def sc_mulsub(a, b, c):
#takes in a, b, and c
#This is used by the regular sig
#i.e. in generate_signature
#returns c-ab mod l
a = number.bytes_to_long(a[::-1])
b = number.bytes_to_long(b[::-1])
c = number.bytes_to_long(c[::-1])
return (c - a * b) % CURVE_P
##########################################
#Hashing
#this is where keccak, H_p, and H_s come in..
######################################
def cn_fast_hash(key, size):
#see ReadMeKeccak.txt
return KEK.Keccak((size,key.encode("hex")),1088,512,256,False)
###################################################
#CryptoNote Things
#Mainly from https://github.com/monero-project/bitmonero/blob/1b8a68f6c1abcf481652c2cfd87300a128e3eb32/src/crypto/crypto.cpp
###################################################
def random_scalar():
tmp = rand.getrandbits(64 * 8) # 8 bits to a byte ...
tmp = sc_reduce(tmp) #-> turns 64 to 32 (note sure why don't just gt 32 in first place ... )
return tmp
def hash_to_scalar(data, length):
#this one is H_s(P)
#relies on cn_fast_hash and sc_reduce32 (which makes an int smaller)
#the input here is not necessarily a 64 byte thing, and that's why sc_reduce32
res = hexToLong(cn_fast_hash(data, length))
return sc_reduce32(res)
def generate_keys():
#should return a secret key and public key pair
#once you have the secret key,
#then the public key be gotten from 25519 function
#so just need to generate random
#first generate random 32-byte(256 bit) integer, copy to result
#ok, just sc_reduce, what that does is takes 64 byte int, turns into 32 byte int...
#so sc_reduce is legit and comes from another library http://hackage.haskell.org/package/ed25519-0.0.2.0/src/src/cbits/sc_reduce.c
#as far as I can tell, sc
#basically this gets you an int which is sufficiently large
#import Crypto.Random.random as rand
rng = random_scalar()
#sec = hex(rng).rstrip("L").lstrip("0x") or "0"
sec = sc_reduce32(rng)
pub = public_key(sec).encode("hex")
#pub = ge_scalarmult_base(sec)
#print(rng.decode("hex"))
#sec = curve25519_mult(rng, basepoint)
#the point of ge_p3_tobytes here is just store as bytes...
#and p3 is a way to store points on the ge curve
return sec, pub
def check_key(key):
#inputs a public key, and outputs if point is on the curve
return isoncurve(toPoint(key))
def secret_key_to_public_key(secret_key):
#the actual function returns as bytes since they mult the fast way.
if sc_check(secret_key) != 0:
print "error in sc_check"
quit()
return public_key(secret_key)
def hash_to_ec(key):
#takes a hash and turns into a point on the curve
#In MININERO, I'm not using the byte representation
#So this function is superfluous
h = hash_to_scalar(key, len(key))
point = ge_scalarmult_base(h)
return ge_mul8(point)
def generate_key_image(public_key, secret_key):
#should return a key image as defined in whitepaper
if sc_check(secret_key) != 0:
print"sc check error in key image"
point = hash_to_ec(public_key)
point2 = ge_scalarmult(secret_key, point)
return point2
def generate_ring_signature(prefix, image, pubs, pubs_count, sec, sec_index):
#returns a ring signature
if sec_index >= pubs_count:
print "bad index of secret key!"
quit()
if ge_frombytes_vartime(image) != 0:
print"bad image!"
quit()
summ = 0
aba = [0 for xx in range(pubs_count)]
abb = [0 for xx in range(pubs_count)]
sigc = [0 for xx in range(pubs_count)] #these are the c[i]'s from the whitepaper
sigr =[0 for xx in range(pubs_count)] #these are the r[i]'s from the whitepaper
for ii in range(0, pubs_count):
if (ii == sec_index):
kk = random_scalar()
tmp3 = ge_scalarmult_base(kk) #L[i] for i = s
aba[ii] = tmp3
tmp3 = hash_to_ec(pubs[ii]) #R[i] for i = s
abb[ii] = ge_scalarmult(kk, tmp3)
else:
k1 = random_scalar() #note this generates a random scalar in the correct range...
k2 = random_scalar()
if ge_frombytes_vartime(pubs[ii]) != 0:
print "error in ring sig!!!"
quit()
tmp2 = ge_double_scalarmult_base_vartime(k1, pubs[ii], k2) #this is L[i] for i != s
aba[ii] = tmp2
tmp3 = hash_to_ec(pubs[ii])
abb[ii] = ge_double_scalarmult_vartime(k2, tmp3, k1, image) #R[i] for i != s
sigc[ii] = k1 #the random c[i] for i != s
sigr[ii] = k2 #the random r[i] for i != s
summ = sc_add(summ, sigc[ii]) #summing the c[i] to get the c[s] via page 9 whitepaper
buf = struct.pack('64s', prefix)
for ii in range(0, pubs_count):
buf += struct.pack('64s', aba[ii])
buf += struct.pack('64s', abb[ii])
hh = hash_to_scalar(buf,len(buf))
sigc[sec_index] = sc_sub(hh, summ) # c[s] = hash - sum c[i] mod l
sigr[sec_index] = sc_mulsub(sigc[sec_index], sec, kk) # r[s] = q[s] - sec * c[index]
return image, sigc, sigr
def check_ring_signature(prefix, key_image, pubs, pubs_count, sigr, sigc):
#from https://github.com/monero-project/bitmonero/blob/6a70de32bf872d97f9eebc7564f1ee41ff149c36/src/crypto/crypto.cpp
#this is the "ver" algorithm
aba = [0 for xx in range(pubs_count)]
abb = [0 for xx in range(pubs_count)]
if ge_frombytes_vartime(key_image) != 0:
print "ring image error in checking sigs"
quit()
summ = 0
buf = struct.pack('64s', prefix)
for ii in range(0, pubs_count):
if ((sc_check(sigc[ii]) != 0) or (sc_check(sigr[ii]) != 0)):
print "failed sc_check in check ring sigs"
quit()
if ge_frombytes_vartime(pubs[ii]) != 0:
print "public key is a bad point in ring sigs"
quit()
tmp2 = ge_double_scalarmult_base_vartime(sigc[ii], pubs[ii], sigr[ii])
aba[ii] = tmp2
tmp3 = hash_to_ec(pubs[ii])
tmp2 = ge_double_scalarmult_vartime(sigr[ii], tmp3, sigc[ii], key_image)
abb[ii] = tmp2
summ = sc_add(summ, sigc[ii])
for ii in range(0, pubs_count):
buf += struct.pack('64s', aba[ii])
buf += struct.pack('64s', abb[ii])
hh = hash_to_scalar(buf,len(buf))
hh = sc_sub(hh, summ)
return sc_isnonzero(hh) == 0
def generate_key_derivation(key1, key2):
#key1 is public key of receiver Bob (see page 7)
#key2 is Alice's private
#this is a helper function for the key-derivation
#which is the generating one-time key's thingy
if sc_check(key2) != 0:
#checks that the secret key is uniform enough...
print"error in sc_check in keyder"
quit()
if ge_frombytes_vartime(key1) != 0:
print "didn't pass curve checks in keyder"
quit()
point = key1 ## this ones the public
point2 = ge_scalarmult( key2, point)
#print("p2", encodepoint(point2).encode("hex"))
point3 = ge_mul8(point2) #This has to do with n==0 mod 8 by dedfinition, c.f. the top paragraph of page 5 of http://cr.yp.to/ecdh/curve25519-20060209.pdf
#and also c.f. middle of page 8 in same document (Bernstein)
return point3
def derivation_to_scalar(derivation, output_index):
#this function specifically hashes your
#output index (for the one time keys )
#in order to get an int, so we can do ge_mult_scalar
#buf = s_comm(d = derivation, o = output_index)
buf2 = struct.pack('64sl', derivation, output_index)
#print(buf2)
return hash_to_scalar(buf2, len(buf2))
def derive_public_key(derivation, output_index, base ):
if ge_frombytes_vartime(base) != 0: #check some conditions on the point
print"derive pub key bad point"
quit()
point1 = base
scalar = derivation_to_scalar(derivation, output_index)
point2 = ge_scalarmult_base(scalar)
point3 = point2 #I think the cached is just for the sake of adding
#because the CN code adds using the monty curve
point4 = edwards(toPoint(point1), toPoint(point3))
return point4
def sc_add(aa, bb):
return (aa + bb ) %CURVE_P
def sc_sub(aa, bb):
return (aa - bb ) %CURVE_P
def sc_isnonzero(c):
return (c %CURVE_P != 0 )
def sc_mulsub(aa, bb, cc):
return (cc - aa * bb ) %CURVE_P
def derive_secret_key(derivation, output_index, base):
#outputs a derived key...
if sc_check(base) !=0:
print"cs_check in derive_secret_key"
scalar = derivation_to_scalar(derivation, output_index)
return base + scalar
class s_comm:
def __init__(self, **kwds):
self.__dict__.update(kwds)
def generate_signature(prefix_hash, pub, sec):
#gets the "usual" signature (not ring sig)
#buf = s_comm(h=prefix_hash, key=pub, comm=0) #see the pack below
k = random_scalar()
tmp3 = ge_scalarmult_base(k)
buf2 = struct.pack('64s64s64s', prefix_hash, pub, tmp3)
sigc = hash_to_scalar(buf2, len(buf2))
return sc_mulsub(sigc, sec, k), sigc
def check_signature(prefix_hash, pub, sigr, sigc):
#checking the normal sigs, not the ring sigs...
if ge_frombytes_vartime(pub) !=0:
print "bad point, check sig!"
quit()
if (sc_check(sigc) != 0) or (sc_check(sigr) != 0):
print"sc checksig error!"
quit()
tmp2 = ge_double_scalarmult_base_vartime(sigc, pub, sigr)
buf2 = struct.pack('64s64s64s', prefix_hash, pub, tmp2)
c = hash_to_scalar(buf2, len(buf2))
c = sc_sub(c, sigc)
return sc_isnonzero(c) == 0
def hexToLong(a):
return number.bytes_to_long(a.decode("hex"))
def longToHex(a):
return number.long_to_bytes(a).encode("hex")
def hexToBits(a):
return a.decode("hex")
def bitsToHex(a):
return a.encode("hex")
def sc_check(key):
#in other words, keys which are too small are rejected
return 0
#s0, s1, s2, s3, s4, s5, s6, s7 = load_4(longToHex(key))
#return (signum_(1559614444 - s0) + (signum_(1477600026 - s1) << 1) + (signum_(2734136534 - s2) << 2) + (signum_(350157278 - s3) << 3) + (signum_(-s4) << 4) + (signum_(-s5) << 5) + (signum_(-s6) << 6) + (signum_(268435456 - s7) << 7)) >> 8
if __name__ == "__main__":
if sys.argv[1] == "rs":
#test random_scalar
print(longToHex(random_scalar()))
if sys.argv[1] == "keys":
#test generating keys
x,P = generate_keys()
print"generating keys:"
print("secret:")
print( x)
print("public:")
print( P)
print("the point P")
print(decodepoint(P.decode("hex")))
if sys.argv[1] == "fasthash":
mysecret = "99b66345829d8c05041eea1ba1ed5b2984c3e5ec7a756ef053473c7f22b49f14"
output_index = 2
buf2 = struct.pack('64sl', mysecret, output_index)
#buf2 = pickle(buf)
#print(buf2)
print(buf2)
print(cn_fast_hash(mysecret, len(mysecret)))
print(cn_fast_hash(buf2, len(buf2)))
if sys.argv[1] == "hashscalar":
data = "ILOVECATS"
print(cn_fast_hash(data, len(data)))
print(hash_to_scalar(data, len(data)))
if sys.argv[1] == "hashcurve":
data = "ILOVECATS"
print(cn_fast_hash(data, len(data)))
print(hash_to_ec(data))
if sys.argv[1] == "checkkey":
x, P = generate_keys()
print(check_key(P))
if sys.argv[1] == "secpub":
#testing for secret_key_to_public_key
#these test vecs were for the monty implementation
mysecret = "99b66345829d8c05041eea1ba1ed5b2984c3e5ec7a756ef053473c7f22b49f14"
mypublic = "b1c652786697a5feef36a56f36fde524a21193f4e563627977ab515f600fdb3a"
mysecret, P = generate_keys()
pub2 = secret_key_to_public_key(mysecret)
print(pub2.encode("hex"))
if sys.argv[1] == "keyder":
#testing for generate_key_derivation
x,P = generate_keys()
print(x, P)
print(generate_key_derivation(P, x))
if sys.argv[1] == "dersca":
#testing for derivation_to_scalar
#this is getting a scalar for one-time-keys rH_s(P)
aa, AA = generate_keys()
bb, BB = generate_keys()
for i in range(0,3):
rr, ZZ = generate_keys()
derivation = generate_key_derivation(BB, aa)
s = derivation_to_scalar(derivation, i)
print(s)
if sys.argv[1] == "derpub":
x, P = generate_keys()
output_index = 5
keyder = generate_key_derivation(P, x)
print("keyder", keyder)
print(derive_public_key(keyder, output_index, P))
if sys.argv[1] == "dersec":
x, P = generate_keys()
output_index = 5
keyder = generate_key_derivation(P, x)
print("keyder", keyder)
print(derive_secret_key(keyder, output_index, x))
if sys.argv[1] == "testcomm":
a = "99b66345829d8c05041eea1ba1ed5b2984c3e5ec7a756ef053473c7f22b49f14"
co2 = struct.pack('hhl', 1, 2, 3)
print(co2.encode("hex")) #sometimes doesn't print if your terminal doesn't have unicode
if sys.argv[1] == "gensig":
#testing generate_signature
print""
prefix = "destination"
sec, pub = generate_keys() # just to have some data to use ..
print(generate_signature(prefix, pub, sec))
if sys.argv[1] == "checksig":
prefix = "destination"
sec, pub = generate_keys() # just to have some data to use ..
sir, sic = generate_signature(prefix, pub, sec)
print(sir, sic)
print(check_signature(prefix, pub, sir, sic))
if sys.argv[1] == "keyimage":
x, P = generate_keys()
xb = 14662008266461539177776197088974240017016792645044069572180060425138978088469
Pb = "1d0ecd1758a685d88b39567f491bc93129f59c7dae7182bddc4e6f5ad38ba462"
I = generate_key_image(Pb, xb)
print(I)
if sys.argv[1] == "ringsig":
#these are fixed since my computer runs out of memory
xa = 54592381732429499113512315392038591381134951436395595620076310715410049314218
Pa = "3c853b5a82912313b179e40d655003c5e3112c041fcf755c3f09d2a8c64d9062"
xb = 14662008266461539177776197088974240017016792645044069572180060425138978088469
Pb = "1d0ecd1758a685d88b39567f491bc93129f59c7dae7182bddc4e6f5ad38ba462"
ima = "0620b888780351a3029dfbf1a5c45a89816f118aa63fa807d51b959cb3c5efc9"
ima, sic, sir = generate_ring_signature("dest", ima, [Pa, Pb],2, xb, 1)
print("ima",ima)
print("sic", sir)
print("sir", sic)
print(check_ring_signature("dest", ima, [Pa, Pb], 2, sir, sic))
if sys.argv[1] == "conv":
#testing reduction
a = "99b66345829d8c05041eea1ba1ed5b2984c3e5ec7a756ef053473c7f22b49f14"
print(a)
r = hexToLong(a)
print(r)
a = longToHex(r)
print(a)
if sys.argv[1] == "red":
a = "99b66345829d8c05041eea1ba1ed5b2984c3e5ec7a756ef053473c7f22b49f14"
tmp = rand.getrandbits(64 * 8)
tmp2 = longToHex(tmp)
print(tmp2)
tmp3 = longToHex(sc_reduce(tmp))
print(tmp3)
tmp4 = sc_reduce32(CURVE_P + 1)
print(tmp4)
tmp5 = sc_reduce(CURVE_P + 1)
print(tmp5)
if sys.argv[1] == "gedb":
x, P = generate_keys()
print(ge_double_scalarmult_base_vartime(x, P, x))
if sys.argv[1] == "sck":
#testing sc_check
x, P = generate_keys()
print(sc_check(x))
print("nonreduced", longToHex(x))
print("reduced", sc_reduce32_2(x))
print("check reduced", sc_check(hexToLong(sc_reduce32_2(x))))

View file

@ -0,0 +1,10 @@
import hashlib #for signatures
import math
import Crypto.Random.random as rand
import Keccak #cn_fast_hash
import mnemonic #making 25 word mnemonic to remember your keys
import binascii #conversion between hex, int, and binary. Also for the crc32 thing
import ed25519 #Bernsteins python ed25519 code from cr.yp.to
import zlib

View file

@ -0,0 +1,5 @@
import ed25519
import MiniNero
import binascii
print(MiniNero.getHForCT())

File diff suppressed because one or more lines are too long