Merge pull request #1 from ShenNoether/master

Added MRL0005 formatted, RingCT code and updated MiniNero code
This commit is contained in:
Riccardo Spagni 2016-02-05 22:30:58 +02:00
commit 8ab5e066dd
96 changed files with 33954 additions and 1 deletions

View file

@ -0,0 +1,145 @@
@article{abe,
title={1-out-of-n signatures from a variety of keys},
author={Abe, Masayuki and Ohkubo, Miyako and Suzuki, Koutarou},
journal={Advances in Cryptology?Asiacrypt 2002},
pages={415--432},
year={2002},
publisher={Springer Berlin Heidelberg}
}
@misc{B,
author = {Back, Adam},
title = {Ring Signature Efficiency},
howpublished = {\url{https://bitcointalk.org/index.php?topic=972541.msg10619684\#msg10619684}},
year = {2015},
note = "[Online; accessed 1-May-2015]"
}
@misc{B2,
author = {Back, Adam},
title = {Bitcoins With Homomorphic Value (Validatable But Encrypted)},
howpublished = {\url{https://bitcointalk.org/index.php?topic=305791.0}},
year = {2013},
note = "[Online; accessed 1-May-2015]"
}
@article{CN,
title={Cryptonote v 2. 0},
author={van Saberhagen, Nicolas},
journal={HYPERLINK \url{https://cryptonote.org/whitepaper.pdf}},
year={2013}
}
@article{DASH,
title={Darkcoin: PeertoPeer CryptoCurrency with Anonymous Blockchain Transactions and an Improved ProofofWork System},
author={Duffield, Evan and Hagan, Kyle},
year={2014}
}
@incollection{FS,
title={Traceable ring signature},
author={Fujisaki, Eiichiro and Suzuki, Koutarou},
booktitle={Public Key Cryptography--PKC 2007},
pages={181--200},
year={2007},
publisher={Springer}
}
@misc{GMc,
title={CoinJoin: Bitcoin privacy for the real world, August 2013},
author={Maxwell, Greg},
howpublished = {Bitcoin Forum. \url{https://bitcointalk.org/index.php?topic=279249.0}},
year = {2013},
note = "[Online; accessed 1-July-2015]"
}
@misc{GM,
title={{Confidential Transactions}},
author={Maxwell, Greg},
howpublished = {\url{https://people.xiph.org/~greg/confidential_values.txt}},
year = {2015},
note = "[Online; accessed 1-June-2015]"
}
@misc{herranz,
author = "Herranz, Javier",
title = "Aggregate Signatures",
month = "oct",
year = "2005",
howpublished={\url{http://www.iiia.csic.es/~jherranz/papers/Nijmegen_seminar_aggregate.pdf}}
}
@inproceedings{LWW,
title={Linkable spontaneous anonymous group signature for ad hoc groups},
author={Liu, Joseph K and Wei, Victor K and Wong, Duncan S},
booktitle={Information Security and Privacy},
pages={325--335},
year={2004},
organization={Springer}
}
@misc {mrl4,
author = {Adam Mackenzie and Surae Noether and Monero Core Team},
title = "Improving Obfuscation in the CryptoNote Protocol",
month = "January",
year = "2015",
howpublished = {\url{"https://lab.getmonero.org/pubs/MRL-0004.pdf"}}
}
@incollection{RST,
title={How to leak a secret},
author={Rivest, Ronald L and Shamir, Adi and Tauman, Yael},
booktitle={Advances in Cryptology???ASIACRYPT 2001},
pages={552--565},
year={2001},
publisher={Springer}
}
@misc{Snoe,
author = {Noether, Shen},
title = {MiniNero},
year = {2015},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/ShenNoether/MiniNero}},
commit = {e2dae45626295c9c49661ab227ee9823b79a6960}
}
@misc{El,
author = {Maxwell, Greg},
title = {Elements Project},
year = {2015},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/ShenNoether/MiniNero}},
commit = {8c323e0accaad3a1e17296448931ce1d557d9bc5}
}
@article{SN,
title={Bitcoin: A peer-to-peer electronic cash system},
author={Nakamoto, Satoshi},
journal={Consulted},
volume={1},
number={2012},
pages={28},
year={2008}
}
@inproceedings{Z,
title={Zerocash: Decentralized anonymous payments from Bitcoin},
author={Ben Sasson, Eli and Chiesa, Alessandro and Garman, Christina and Green, Matthew and Miers, Ian and Tromer, Eran and Virza, Madars},
booktitle={Security and Privacy (SP), 2014 IEEE Symposium on},
pages={459--474},
year={2014},
organization={IEEE}
}

View file

@ -579,7 +579,6 @@
\def\runtitle#1{\gdef\@runtitle{#1}}
\def\runauthor#1{\gdef\@runauthor{#1}\global\let\copauthor\@runauthor}
\def\@runauthor{}
\def\@lastpage{0}
\def\thepage@fmt#1{Page #1 of \@lastpage}
@ -847,6 +846,7 @@
\setattribute{address} {text} {Author details}
\setattribute{corref} {text} {Correspondence: }
\setattribute{authorinfo} {text} {}
\setattribute{presentaddress} {text} {\textit{Present address: }}
\setattribute{copyright} {text} {\copyright\,\textit{\journal@name}}
\setattribute{runninghead} {text} {\copyright\,\textit{\journal@name} \hfill \thepage@fmt{\thepage}}

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

209
source-code/RingCT/Test.cpp Normal file
View file

@ -0,0 +1,209 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <tuple>
#include <limits>
#include <cstddef>
#include <iostream>
#include "crypto-ops.h"
#include "crypto.h"
#include "keccak.h"
#define DBG
#include "rctTypes.h"
#include "rctOps.h"
#include "rctSigs.h"
#define BYTES 64
using namespace crypto;
using namespace std;
using namespace rct;
int main(int argc, char *argv[]) {
DP("Running tests for ASNL, MG sigs, and Ring CT");
//Schnorr NonLinkable true one and false one
DP("Schnorr non-linkable tests");
//x, P1 = PaperWallet.skpkGen()
key x, P1;
skpkGen(x, P1);
key P2 = pkGen();
key P3 = pkGen();
//L1, s1, s2 = ASNL.GenSchnorrNonLinkable(x, P1, P2, 0)
key L1, s1, s2;
GenSchnorrNonLinkable(L1, s1, s2, x, P1, P2, 0);
DP("This one should verify!");
DP(VerSchnorrNonLinkable(P1, P2, L1, s1, s2));
DP("");
DP("This one should NOT verify!");
DP(VerSchnorrNonLinkable(P1, P3, L1, s1, s2));
//Tests for ASNL
//#ASNL true one, false one, C != sum Ci, and one out of the range..
DP("\n\n ASNL tests");
int N = 64;
key64 xv;
key64 P1v;
key64 P2v;
bits indi;
int j = 0;
for (j = 0 ; j < N ; j++) {
indi[j] = (int)randXmrAmount(1);
xv[j] = skGen();
if ( indi[j] == 0 ) {
P1v[j] = scalarmultBase(xv[j]);
P2v[j] = pkGen();
} else {
P2v[j] = scalarmultBase(xv[j]);
P1v[j] = pkGen();
}
}
asnlSig L1s2s = GenASNL(xv, P1v, P2v, indi);
//#true one
DP("This one should verify!");
DP(VerASNL(P1v, P2v, L1s2s));
//#false one
indi[3] = (indi[3] + 1) % 2;
DP("");
DP("This one should NOT verify!");
L1s2s = GenASNL(xv, P1v, P2v, indi);
DP(VerASNL(P1v, P2v, L1s2s));
DP("\n\nMG sig tests");
//Tests for MG Sigs
//#MG sig: true one
N = 3;// #cols
int R = 3;// #rows
keyV xtmp = skvGen(R);
keyM xm = keyMInit(R, N);// = [[None]*N] #just used to generate test public keys
keyV sk = skvGen(R);
keyM P = keyMInit(R, N);// = keyM[[None]*N] #stores the public keys;
DP("MG Sig: this one should verify!");
int ind = 2;
int i = 0;
for (j = 0 ; j < R ; j++) {
for (i = 0 ; i < N ; i++)
{
xm[i][j] = skGen();
P[i][j] = scalarmultBase(xm[i][j]);
}
}
for (j = 0 ; j < R ; j++) {
sk[j] = xm[ind][j];
}
mgSig IIccss = MLSAG_Gen(P, sk, ind);
DP("Sig verified?");
DP(MLSAG_Ver(P, IIccss) );
//#MG sig: false one
DP("MG Sig: this one should NOT verify!");
N = 3;// #cols
R = 3;// #rows
xtmp = skvGen(R);
keyM xx(N, xtmp);// = [[None]*N] #just used to generate test public keys
sk = skvGen(R);
//P (N, xtmp);// = keyM[[None]*N] #stores the public keys;
ind = 2;
for (j = 0 ; j < R ; j++) {
for (i = 0 ; i < N ; i++)
{
xx[i][j] = skGen();
P[i][j] = scalarmultBase(xx[i][j]);
}
sk[j] = xx[ind][j];
}
sk[2] = skGen();//asume we don't know one of the private keys..
IIccss = MLSAG_Gen(P, sk, ind);
DP("Sig verified?");
DP(MLSAG_Ver(P, IIccss) );
//Ring CT Stuff
//ct range proofs
DP("\n\n Ring CT tests");
DP("Everything below should verify!");
ctkeyV sc, pc;
ctkey sctmp, pctmp;
//add fake input 5000
tie(sctmp, pctmp) = ctskpkGen(6000);
sc.push_back(sctmp);
pc.push_back(pctmp);
tie(sctmp, pctmp) = ctskpkGen(7000);
sc.push_back(sctmp);
pc.push_back(pctmp);
vector<xmr_amount >amounts;
//add output 500
amounts.push_back(500);
keyV destinations;
key Sk, Pk;
skpkGen(Sk, Pk);
destinations.push_back(Pk);
//add output for 12500
amounts.push_back(12500);
skpkGen(Sk, Pk);
destinations.push_back(Pk);
//compute rct data with mixin 500
DP("computing ring ct sig with mixin 500");
rctSig s = genRct(sc, pc, destinations, amounts, 500);
//verify rct data
DP("test sig verifies?");
DP(verRct(s));
//decode received amount
DP("decode amounts working?");
DP(decodeRct(s, Sk, 1));
DP("\nRing CT with failing MG sig part should not verify!");
DP("Since sum of inputs != outputs");
amounts[1] = 12501;
skpkGen(Sk, Pk);
destinations[1] = Pk;
//compute rct data with mixin 500
s = genRct(sc, pc, destinations, amounts, 500);
//verify rct data
DP("test sig verifies?");
DP(verRct(s));
//decode received amount
DP("decode amounts working?");
DP(decodeRct(s, Sk, 1));
return 0;
}

View file

@ -0,0 +1,842 @@
#include <stdint.h>
#include "crypto-ops.h"
/* sqrt(x) is such an integer y that 0 <= y <= p - 1, y % 2 = 0, and y^2 = x (mod p). */
/* d = -121665 / 121666 */
const fe fe_d = {-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116}; /* d */
const fe fe_sqrtm1 = {-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482}; /* sqrt(-1) */
const fe fe_d2 = {-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199}; /* 2 * d */
/* base[i][j] = (j+1)*256^i*B */
const ge_precomp ge_base[32][8] = {
{
{{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}},
{{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303},
{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081},
{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}},
{{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}},
{{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540},
{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397},
{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}},
{{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}},
{{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777},
{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737},
{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}},
{{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}},
{{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726},
{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955},
{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}}
}, {
{{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171},
{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510},
{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}},
{{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639},
{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963},
{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}},
{{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568},
{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335},
{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}},
{{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007},
{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772},
{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}},
{{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567},
{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686},
{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}},
{{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887},
{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954},
{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}},
{{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833},
{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532},
{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}},
{{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268},
{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214},
{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}}
}, {
{{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800},
{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645},
{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}},
{{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933},
{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182},
{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}},
{{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991},
{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880},
{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}},
{{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295},
{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788},
{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}},
{{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026},
{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347},
{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}},
{{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395},
{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278},
{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}},
{{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995},
{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596},
{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}},
{{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060},
{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608},
{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}}
}, {
{{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389},
{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016},
{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}},
{{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505},
{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553},
{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}},
{{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220},
{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631},
{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}},
{{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556},
{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749},
{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}},
{{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391},
{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253},
{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}},
{{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958},
{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082},
{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}},
{{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521},
{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807},
{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}},
{{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134},
{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455},
{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}}
}, {
{{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069},
{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746},
{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}},
{{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837},
{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906},
{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}},
{{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817},
{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098},
{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}},
{{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504},
{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727},
{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}},
{{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003},
{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605},
{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}},
{{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701},
{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683},
{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}},
{{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563},
{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260},
{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}},
{{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672},
{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686},
{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}}
}, {
{{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182},
{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277},
{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}},
{{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474},
{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539},
{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}},
{{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970},
{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756},
{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}},
{{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683},
{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655},
{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}},
{{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125},
{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839},
{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}},
{{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294},
{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899},
{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}},
{{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294},
{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949},
{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}},
{{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420},
{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940},
{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}}
}, {
{{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567},
{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127},
{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}},
{{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887},
{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964},
{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}},
{{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244},
{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999},
{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}},
{{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274},
{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236},
{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}},
{{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761},
{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884},
{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}},
{{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638},
{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490},
{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}},
{{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736},
{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124},
{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}},
{{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029},
{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048},
{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}}
}, {
{{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593},
{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071},
{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}},
{{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687},
{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441},
{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}},
{{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460},
{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007},
{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}},
{{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005},
{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674},
{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}},
{{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590},
{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957},
{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}},
{{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740},
{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122},
{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}},
{{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885},
{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140},
{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}},
{{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155},
{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260},
{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}}
}, {
{{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677},
{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815},
{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}},
{{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203},
{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208},
{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}},
{{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850},
{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389},
{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}},
{{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689},
{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880},
{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}},
{{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632},
{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412},
{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}},
{{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038},
{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232},
{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}},
{{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856},
{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738},
{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}},
{{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718},
{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697},
{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}}
}, {
{{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912},
{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358},
{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}},
{{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307},
{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977},
{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}},
{{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644},
{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616},
{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}},
{{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099},
{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341},
{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}},
{{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646},
{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425},
{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}},
{{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743},
{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822},
{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}},
{{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985},
{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702},
{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}},
{{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293},
{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100},
{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}}
}, {
{{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186},
{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610},
{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}},
{{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220},
{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025},
{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}},
{{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992},
{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027},
{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}},
{{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901},
{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952},
{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}},
{{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390},
{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730},
{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}},
{{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180},
{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272},
{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}},
{{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970},
{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772},
{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}},
{{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750},
{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373},
{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}}
}, {
{{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144},
{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195},
{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}},
{{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684},
{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518},
{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}},
{{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793},
{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794},
{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}},
{{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921},
{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518},
{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}},
{{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278},
{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024},
{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}},
{{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783},
{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717},
{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}},
{{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333},
{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048},
{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}},
{{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760},
{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757},
{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}}
}, {
{{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468},
{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184},
{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}},
{{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066},
{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882},
{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}},
{{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101},
{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279},
{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}},
{{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709},
{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714},
{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}},
{{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464},
{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847},
{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}},
{{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414},
{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158},
{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}},
{{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415},
{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459},
{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}},
{{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412},
{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743},
{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}}
}, {
{{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022},
{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429},
{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}},
{{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861},
{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000},
{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}},
{{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815},
{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642},
{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}},
{{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574},
{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742},
{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}},
{{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020},
{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772},
{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}},
{{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953},
{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218},
{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}},
{{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073},
{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325},
{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}},
{{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870},
{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863},
{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}}
}, {
{{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267},
{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663},
{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}},
{{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673},
{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943},
{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}},
{{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238},
{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064},
{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}},
{{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052},
{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904},
{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}},
{{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979},
{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841},
{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}},
{{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324},
{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940},
{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}},
{{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184},
{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114},
{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}},
{{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784},
{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091},
{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}}
}, {
{{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208},
{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864},
{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}},
{{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233},
{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212},
{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}},
{{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068},
{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397},
{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}},
{{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889},
{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038},
{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}},
{{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875},
{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905},
{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}},
{{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818},
{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714},
{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}},
{{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931},
{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024},
{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}},
{{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204},
{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817},
{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}}
}, {
{{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504},
{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768},
{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}},
{{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790},
{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438},
{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}},
{{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971},
{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905},
{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}},
{{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409},
{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499},
{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}},
{{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664},
{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324},
{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}},
{{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990},
{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914},
{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}},
{{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257},
{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433},
{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}},
{{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045},
{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093},
{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}}
}, {
{{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191},
{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507},
{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}},
{{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018},
{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109},
{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}},
{{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528},
{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625},
{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}},
{{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033},
{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866},
{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}},
{{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075},
{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347},
{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}},
{{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165},
{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588},
{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}},
{{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017},
{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883},
{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}},
{{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043},
{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663},
{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}}
}, {
{{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860},
{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466},
{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}},
{{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997},
{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295},
{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}},
{{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385},
{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109},
{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}},
{{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424},
{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185},
{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}},
{{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325},
{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593},
{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}},
{{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644},
{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801},
{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}},
{{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884},
{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577},
{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}},
{{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473},
{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644},
{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}}
}, {
{{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599},
{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768},
{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}},
{{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328},
{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369},
{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}},
{{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815},
{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025},
{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}},
{{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448},
{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981},
{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}},
{{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501},
{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073},
{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}},
{{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845},
{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211},
{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}},
{{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096},
{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803},
{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}},
{{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965},
{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505},
{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}}
}, {
{{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782},
{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900},
{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}},
{{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208},
{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232},
{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}},
{{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271},
{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326},
{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}},
{{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300},
{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570},
{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}},
{{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994},
{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913},
{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}},
{{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730},
{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096},
{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}},
{{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411},
{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905},
{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}},
{{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870},
{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498},
{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}}
}, {
{{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677},
{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647},
{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}},
{{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468},
{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375},
{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}},
{{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725},
{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612},
{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}},
{{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944},
{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928},
{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}},
{{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139},
{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963},
{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}},
{{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734},
{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680},
{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}},
{{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931},
{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654},
{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}},
{{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180},
{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684},
{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}}
}, {
{{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501},
{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413},
{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}},
{{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874},
{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962},
{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}},
{{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152},
{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063},
{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}},
{{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146},
{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183},
{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}},
{{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421},
{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622},
{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}},
{{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663},
{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753},
{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}},
{{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862},
{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118},
{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}},
{{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380},
{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824},
{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}}
}, {
{{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438},
{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584},
{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}},
{{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471},
{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610},
{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}},
{{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650},
{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369},
{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}},
{{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462},
{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793},
{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}},
{{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226},
{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019},
{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}},
{{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171},
{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132},
{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}},
{{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181},
{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210},
{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}},
{{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935},
{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105},
{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}}
}, {
{{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852},
{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581},
{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}},
{{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844},
{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025},
{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}},
{{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068},
{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192},
{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}},
{{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259},
{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426},
{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}},
{{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305},
{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832},
{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}},
{{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011},
{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447},
{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}},
{{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245},
{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859},
{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}},
{{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707},
{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848},
{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}}
}, {
{{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391},
{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215},
{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}},
{{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713},
{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849},
{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}},
{{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940},
{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031},
{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}},
{{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243},
{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116},
{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}},
{{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509},
{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883},
{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}},
{{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660},
{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273},
{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}},
{{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560},
{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135},
{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}},
{{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739},
{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756},
{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}}
}, {
{{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347},
{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028},
{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}},
{{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799},
{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609},
{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}},
{{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989},
{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523},
{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}},
{{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045},
{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377},
{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}},
{{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016},
{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426},
{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}},
{{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396},
{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080},
{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}},
{{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275},
{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074},
{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}},
{{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717},
{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101},
{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}}
}, {
{{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632},
{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415},
{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}},
{{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876},
{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625},
{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}},
{{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164},
{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595},
{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}},
{{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858},
{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193},
{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}},
{{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942},
{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635},
{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}},
{{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935},
{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415},
{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}},
{{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018},
{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778},
{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}},
{{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385},
{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503},
{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}}
}, {
{{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056},
{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838},
{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}},
{{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691},
{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118},
{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}},
{{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269},
{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904},
{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}},
{{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193},
{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910},
{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}},
{{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667},
{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481},
{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}},
{{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640},
{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278},
{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}},
{{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272},
{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012},
{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}},
{{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046},
{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345},
{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}}
}, {
{{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937},
{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636},
{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}},
{{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429},
{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576},
{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}},
{{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490},
{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104},
{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}},
{{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275},
{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511},
{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}},
{{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439},
{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939},
{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}},
{{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310},
{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608},
{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}},
{{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101},
{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418},
{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}},
{{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356},
{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996},
{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}}
}, {
{{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728},
{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658},
{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}},
{{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001},
{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766},
{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}},
{{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458},
{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628},
{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}},
{{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062},
{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616},
{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}},
{{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383},
{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814},
{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}},
{{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417},
{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222},
{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}},
{{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597},
{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970},
{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}},
{{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647},
{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511},
{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}}
}, {
{{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834},
{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461},
{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}},
{{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516},
{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547},
{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}},
{{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038},
{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741},
{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}},
{{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747},
{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323},
{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}},
{{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373},
{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228},
{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}},
{{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399},
{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831},
{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}},
{{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313},
{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958},
{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}},
{{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743},
{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684},
{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}}
}
};
const ge_precomp ge_Bi[8] = {
{{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}}, {{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}}, {{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}}, {{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}}, {{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877},
{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951},
{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}}, {{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436},
{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918},
{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}}, {{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800},
{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305},
{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}}, {{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876},
{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619},
{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}}
};
/* A = 2 * (1 - d) / (1 + d) = 486662 */
const fe fe_ma2 = {-12721188, -3529, 0, 0, 0, 0, 0, 0, 0, 0}; /* -A^2 */
const fe fe_ma = {-486662, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* -A */
const fe fe_fffb1 = {-31702527, -2466483, -26106795, -12203692, -12169197, -321052, 14850977, -10296299, -16929438, -407568}; /* sqrt(-2 * A * (A + 2)) */
const fe fe_fffb2 = {8166131, -6741800, -17040804, 3154616, 21461005, 1466302, -30876704, -6368709, 10503587, -13363080}; /* sqrt(2 * A * (A + 2)) */
const fe fe_fffb3 = {-13620103, 14639558, 4532995, 7679154, 16815101, -15883539, -22863840, -14813421, 13716513, -6477756}; /* sqrt(-sqrt(-1) * A * (A + 2)) */
const fe fe_fffb4 = {-21786234, -12173074, 21573800, 4524538, -4645904, 16204591, 8012863, -8444712, 3212926, 6885324}; /* sqrt(sqrt(-1) * A * (A + 2)) */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,150 @@
// Copyright (c) 2014-2015, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
/* From fe.h */
typedef int32_t fe[10];
/* From ge.h */
typedef struct {
fe X;
fe Y;
fe Z;
} ge_p2;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p3;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p1p1;
typedef struct {
fe yplusx;
fe yminusx;
fe xy2d;
} ge_precomp;
typedef struct {
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
} ge_cached;
/* From ge_add.c */
void ge_add(ge_p1p1 *, const ge_p3 *, const ge_cached *);
/* From ge_sub.c */
void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *);
/* From ge_double_scalarmult.c, modified */
typedef ge_cached ge_dsmp[8];
extern const ge_precomp ge_Bi[8];
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s);
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *);
/* From ge_frombytes.c, modified */
extern const fe fe_sqrtm1;
extern const fe fe_d;
int ge_frombytes_vartime(ge_p3 *, const unsigned char *);
/* From ge_p1p1_to_p2.c */
void ge_p1p1_to_p2(ge_p2 *, const ge_p1p1 *);
/* From ge_p1p1_to_p3.c */
void ge_p1p1_to_p3(ge_p3 *, const ge_p1p1 *);
/* From ge_p2_dbl.c */
void ge_p2_dbl(ge_p1p1 *, const ge_p2 *);
/* From ge_p3_to_cached.c */
extern const fe fe_d2;
void ge_p3_to_cached(ge_cached *, const ge_p3 *);
/* From ge_p3_to_p2.c */
void ge_p3_to_p2(ge_p2 *, const ge_p3 *);
/* From ge_p3_tobytes.c */
void ge_p3_tobytes(unsigned char *, const ge_p3 *);
/* From ge_scalarmult_base.c */
extern const ge_precomp ge_base[32][8];
void ge_scalarmult_base(ge_p3 *, const unsigned char *);
/* From ge_tobytes.c */
void ge_tobytes(unsigned char *, const ge_p2 *);
/* From sc_reduce.c */
void sc_reduce(unsigned char *);
/* New code */
void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *);
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp);
void ge_mul8(ge_p1p1 *, const ge_p2 *);
extern const fe fe_ma2;
extern const fe fe_ma;
extern const fe fe_fffb1;
extern const fe fe_fffb2;
extern const fe fe_fffb3;
extern const fe fe_fffb4;
void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *);
void sc_0(unsigned char *);
void sc_reduce32(unsigned char *);
void sc_reduce32copy(unsigned char *, const unsigned char *);
void sc_add(unsigned char *, const unsigned char *, const unsigned char *);
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *);
void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *);
int sc_check(const unsigned char *);
int sc_isnonzero(const unsigned char *); /* Doesn't normalize */

View file

@ -0,0 +1,364 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <mutex>
#include "varint.h"
#include "warnings.h"
#include "crypto.h"
#include "keccak.h"
#include "hash-ops.h"
#include "generic-ops.h"
#include <stdlib.h>
namespace crypto {
using std::abort;
using std::int32_t;
using std::int64_t;
using std::lock_guard;
using std::mutex;
using std::size_t;
using std::uint32_t;
using std::uint64_t;
extern "C" {
#include "crypto-ops.h"
#include "random.h"
}
mutex random_lock;
static inline unsigned char *operator &(ec_point &point) {
return &reinterpret_cast<unsigned char &>(point);
}
static inline const unsigned char *operator &(const ec_point &point) {
return &reinterpret_cast<const unsigned char &>(point);
}
static inline unsigned char *operator &(ec_scalar &scalar) {
return &reinterpret_cast<unsigned char &>(scalar);
}
static inline const unsigned char *operator &(const ec_scalar &scalar) {
return &reinterpret_cast<const unsigned char &>(scalar);
}
/* generate a random 32-byte (256-bit) integer and copy it to res */
static inline void random_scalar(ec_scalar &res) {
unsigned char tmp[64];
generate_random_bytes(64, tmp);
sc_reduce(tmp);
memcpy(&res, tmp, 32);
}
static void hash_to_scalar(const void *data, size_t length, ec_scalar &res) { //was static inline void
cn_fast_hashh(data, length, reinterpret_cast<hash &>(res)); //this is the void one.. reinterp is trying to get it from ec_scalar to the correct thing...
sc_reduce32(&res);
}
/*
* generate public and secret keys from a random 256-bit integer
* TODO: allow specifiying random value (for wallet recovery)
*
*/
secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) {
lock_guard<mutex> lock(random_lock);
ge_p3 point;
secret_key rng;
if (recover)
{
rng = recovery_key;
}
else
{
random_scalar(rng);
}
sec = rng;
sc_reduce32(&sec); // reduce in case second round of keys (sendkeys)
ge_scalarmult_base(&point, &sec);
ge_p3_tobytes(&pub, &point);
return rng;
}
bool crypto_ops::check_key(const public_key &key) {
ge_p3 point;
return ge_frombytes_vartime(&point, &key) == 0;
}
bool crypto_ops::secret_key_to_public_key(const secret_key &sec, public_key &pub) {
ge_p3 point;
if (sc_check(&sec) != 0) {
return false;
}
ge_scalarmult_base(&point, &sec);
ge_p3_tobytes(&pub, &point);
return true;
}
bool crypto_ops::generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
ge_p3 point;
ge_p2 point2;
ge_p1p1 point3;
assert(sc_check(&key2) == 0);
if (ge_frombytes_vartime(&point, &key1) != 0) {
return false;
}
ge_scalarmult(&point2, &key2, &point);
ge_mul8(&point3, &point2);
ge_p1p1_to_p2(&point2, &point3);
ge_tobytes(&derivation, &point2);
return true;
}
static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
struct {
key_derivation derivation;
char output_index[(sizeof(size_t) * 8 + 6) / 7];
} buf;
char *end = buf.output_index;
buf.derivation = derivation;
tools::write_varint(end, output_index);
assert(end <= buf.output_index + sizeof buf.output_index);
hash_to_scalar(&buf, end - reinterpret_cast<char *>(&buf), res);
}
bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index,
const public_key &base, public_key &derived_key) {
ec_scalar scalar;
ge_p3 point1;
ge_p3 point2;
ge_cached point3;
ge_p1p1 point4;
ge_p2 point5;
if (ge_frombytes_vartime(&point1, &base) != 0) {
return false;
}
derivation_to_scalar(derivation, output_index, scalar);
ge_scalarmult_base(&point2, &scalar);
ge_p3_to_cached(&point3, &point2);
ge_add(&point4, &point1, &point3);
ge_p1p1_to_p2(&point5, &point4);
ge_tobytes(&derived_key, &point5);
return true;
}
void crypto_ops::derive_secret_key(const key_derivation &derivation, size_t output_index,
const secret_key &base, secret_key &derived_key) {
ec_scalar scalar;
assert(sc_check(&base) == 0);
derivation_to_scalar(derivation, output_index, scalar);
sc_add(&derived_key, &base, &scalar);
}
struct s_comm {
hash h;
ec_point key;
ec_point comm;
};
void crypto_ops::generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
lock_guard<mutex> lock(random_lock);
ge_p3 tmp3;
ec_scalar k;
//ec_scalar k = {{0xbf, 0x4b, 0xa0, 0xc8, 0x81, 0xda, 0x40, 0xc9, 0x89, 0x29, 0x27, 0x75, 0x43, 0xe7, 0x38, 0x25, 0xb8, 0xcc, 0x5a, 0x73, 0x21, 0x8a, 0x12, 0x65, 0xa0, 0xf8, 0x33, 0x37, 0x60, 0x17, 0x92, 0x06}}; //uncomment for testing purposes
s_comm buf;
#if !defined(NDEBUG)
{
ge_p3 t;
public_key t2;
assert(sc_check(&sec) == 0);
ge_scalarmult_base(&t, &sec);
ge_p3_tobytes(&t2, &t);
assert(pub == t2);
}
#endif
buf.h = prefix_hash;
buf.key = pub;
random_scalar(k); //fix a scalar k for testing purposes
ge_scalarmult_base(&tmp3, &k);
ge_p3_tobytes(&buf.comm, &tmp3);
//printv(buf.comm.data, "comm"); //testing
hash_to_scalar(&buf, sizeof(s_comm), sig.c);
//printf("here2\n");
sc_mulsub(&sig.r, &sig.c, &sec, &k); //k - c*sec mod l
}
bool crypto_ops::check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
ge_p2 tmp2;
ge_p3 tmp3;
ec_scalar c;
s_comm buf;
assert(check_key(pub));
buf.h = prefix_hash;
buf.key = pub;
if (ge_frombytes_vartime(&tmp3, &pub) != 0) {
abort();
}
if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0) {
return false;
}
ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r); //tmp2 = cP + rG
ge_tobytes(&buf.comm, &tmp2);
hash_to_scalar(&buf, sizeof(s_comm), c);
sc_sub(&c, &c, &sig.c);
return sc_isnonzero(&c) == 0;
}
static void hash_to_ec(const public_key &key, ge_p3 &res) {
hash h;
ge_p2 point;
ge_p1p1 point2;
cn_fast_hashh(std::addressof(key), sizeof(public_key), h);
ge_fromfe_frombytes_vartime(&point, reinterpret_cast<const unsigned char *>(&h));
ge_mul8(&point2, &point);
ge_p1p1_to_p3(&res, &point2);
}
void crypto_ops::generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
ge_p3 point;
ge_p2 point2;
assert(sc_check(&sec) == 0);
hash_to_ec(pub, point);
ge_scalarmult(&point2, &sec, &point);
ge_tobytes(&image, &point2);
}
struct rs_comm {
hash h;
struct {
ec_point a, b;
} ab[];
};
static inline size_t rs_comm_size(size_t pubs_count) {
return sizeof(rs_comm) + pubs_count * sizeof(rs_comm().ab[0]);
}
void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image,
const public_key *const *pubs, size_t pubs_count,
const secret_key &sec, size_t sec_index,
signature *sig) {
lock_guard<mutex> lock(random_lock);
size_t i;
ge_p3 image_unp;
ge_dsmp image_pre;
ec_scalar sum, k, h;
rs_comm *const buf = reinterpret_cast<rs_comm *>(alloca(rs_comm_size(pubs_count)));
assert(sec_index < pubs_count);
#if !defined(NDEBUG)
{
ge_p3 t;
public_key t2;
key_image t3;
assert(sc_check(&sec) == 0);
ge_scalarmult_base(&t, &sec);
ge_p3_tobytes(&t2, &t);
assert(*pubs[sec_index] == t2);
generate_key_image(*pubs[sec_index], sec, t3);
assert(image == t3);
for (i = 0; i < pubs_count; i++) {
assert(check_key(*pubs[i]));
}
}
#endif
if (ge_frombytes_vartime(&image_unp, &image) != 0) {
abort();
}
ge_dsm_precomp(image_pre, &image_unp);
sc_0(&sum);
buf->h = prefix_hash;
for (i = 0; i < pubs_count; i++) {
ge_p2 tmp2;
ge_p3 tmp3;
if (i == sec_index) {
random_scalar(k);
ge_scalarmult_base(&tmp3, &k);
ge_p3_tobytes(&buf->ab[i].a, &tmp3);
hash_to_ec(*pubs[i], tmp3);
ge_scalarmult(&tmp2, &k, &tmp3);
ge_tobytes(&buf->ab[i].b, &tmp2);
} else {
random_scalar(sig[i].c);
random_scalar(sig[i].r);
if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
abort();
}
ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
ge_tobytes(&buf->ab[i].a, &tmp2);
hash_to_ec(*pubs[i], tmp3);
ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre);
ge_tobytes(&buf->ab[i].b, &tmp2);
sc_add(&sum, &sum, &sig[i].c);
}
}
hash_to_scalar(buf, rs_comm_size(pubs_count), h);
sc_sub(&sig[sec_index].c, &h, &sum);
sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &sec, &k);
}
bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image,
const public_key *const *pubs, size_t pubs_count,
const signature *sig) {
size_t i;
ge_p3 image_unp;
ge_dsmp image_pre;
ec_scalar sum, h;
rs_comm *const buf = reinterpret_cast<rs_comm *>(alloca(rs_comm_size(pubs_count)));
#if !defined(NDEBUG)
for (i = 0; i < pubs_count; i++) {
assert(check_key(*pubs[i]));
}
#endif
if (ge_frombytes_vartime(&image_unp, &image) != 0) {
return false;
}
ge_dsm_precomp(image_pre, &image_unp);
sc_0(&sum);
buf->h = prefix_hash;
for (i = 0; i < pubs_count; i++) {
ge_p2 tmp2;
ge_p3 tmp3;
if (sc_check(&sig[i].c) != 0 || sc_check(&sig[i].r) != 0) {
return false;
}
if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
abort();
}
ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
ge_tobytes(&buf->ab[i].a, &tmp2);
hash_to_ec(*pubs[i], tmp3);
ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre);
ge_tobytes(&buf->ab[i].b, &tmp2);
sc_add(&sum, &sum, &sig[i].c);
}
hash_to_scalar(buf, rs_comm_size(pubs_count), h);
sc_sub(&h, &h, &sum);
return sc_isnonzero(&h) == 0;
}
}
CRYPTO_MAKE_HASHABLE(hash) //these are in generic-ops.h
CRYPTO_MAKE_COMPARABLE(hash8)

258
source-code/RingCT/crypto.h Normal file
View file

@ -0,0 +1,258 @@
#pragma once
#include <cstddef>
#include <mutex>
#include <vector>
#include "generic-ops.h"
#include "crypto-ops.h"
#include "random.h"
#include "keccak.h"
#include "hash-ops.h"
namespace crypto {
extern "C" {
#include "random.h"
}
extern std::mutex random_lock;
#pragma pack(push, 1)
struct hash {
char data[HASH_SIZE]; //HASH_SIZE = 32 I believe..
};
struct hash8 {
char data[8];
};
static_assert(sizeof(hash) == HASH_SIZE, "Invalid structure size");
static_assert(sizeof(hash8) == 8, "Invalid structure size");
/*
Cryptonight hash functions
*/
inline void hash_permutation(union hash_state *state) {
keccakf((uint64_t*)state, 24);
}
inline void hash_process(union hash_state *state, const uint8_t *buf, size_t count) {
keccak1600(buf, count, (uint8_t*)state);
}
inline void cn_fast_hash(const void *data, size_t length, char * hash) {
uint8_t md2[32];
int j = 0;
//printf("length: %d\n", (int)sizeof(data));
keccak((uint8_t *) data, (int)sizeof(data), md2, 32); //note for signatures, you need 96, for just hashing a key you need 32, so it's really best to be able to detect
for (j= 0 ; j < 32 ; j++) {
hash[j] = (unsigned char)md2[j];
}
}
inline void cn_fast_hashh(const void *data, std::size_t length, hash &hash) {
cn_fast_hash(data, length, reinterpret_cast<char *>(&hash));
}
inline hash cn_fast_hash2(const void *data, std::size_t length) {
hash h;
cn_fast_hash(data, length, reinterpret_cast<char *>(&h));
return h;
}
struct ec_point {
char data[32];
};
struct ec_scalar {
char data[32];
};
struct public_key: ec_point {
friend class crypto_ops;
};
struct secret_key: ec_scalar {
friend class crypto_ops;
};
struct public_keyV {
std::vector<public_key> keys;
int rows;
};
struct secret_keyV {
std::vector<secret_key> keys;
int rows;
};
struct public_keyM {
int cols;
int rows;
std::vector<secret_keyV> column_vectors;
};
struct key_derivation: ec_point {
friend class crypto_ops;
};
struct key_image: ec_point {
friend class crypto_ops;
};
struct signature {
ec_scalar c, r;
friend class crypto_ops;
};
#pragma pack(pop)
static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
sizeof(public_key) == 32 && sizeof(secret_key) == 32 &&
sizeof(key_derivation) == 32 && sizeof(key_image) == 32 &&
sizeof(signature) == 64, "Invalid structure size");
class crypto_ops {
crypto_ops();
crypto_ops(const crypto_ops &);
void operator=(const crypto_ops &);
~crypto_ops();
static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
static bool check_key(const public_key &);
friend bool check_key(const public_key &);
static bool secret_key_to_public_key(const secret_key &, public_key &);
friend bool secret_key_to_public_key(const secret_key &, public_key &);
static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &);
static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &);
static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &);
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
static bool check_signature(const hash &, const public_key &, const signature &);
friend bool check_signature(const hash &, const public_key &, const signature &);
static void generate_key_image(const public_key &, const secret_key &, key_image &);
friend void generate_key_image(const public_key &, const secret_key &, key_image &);
static void generate_ring_signature(const hash &, const key_image &,
const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
friend void generate_ring_signature(const hash &, const key_image &,
const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *);
static bool check_ring_signature(const hash &, const key_image &,
const public_key *const *, std::size_t, const signature *);
friend bool check_ring_signature(const hash &, const key_image &,
const public_key *const *, std::size_t, const signature *);
};
/* Generate a value filled with random bytes.
*/
template<typename T>
typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
typename std::remove_cv<T>::type res;
std::lock_guard<std::mutex> lock(random_lock);
generate_random_bytes(sizeof(T), &res);
return res;
}
/* Generate a new key pair
*/
inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
}
/* Check a public key. Returns true if it is valid, false otherwise.
*/
inline bool check_key(const public_key &key) {
return crypto_ops::check_key(key);
}
/* Checks a private key and computes the corresponding public key.
*/
inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) {
return crypto_ops::secret_key_to_public_key(sec, pub);
}
/* To generate an ephemeral key used to send money to:
* * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field.
* * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index.
* * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key.
* * The receiver can either derive the public key (to check that the transaction is addressed to him) or the private key (to spend the money).
*/
inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
return crypto_ops::generate_key_derivation(key1, key2, derivation);
}
inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index,
const public_key &base, public_key &derived_key) {
return crypto_ops::derive_public_key(derivation, output_index, base, derived_key);
}
inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index,
const secret_key &base, secret_key &derived_key) {
crypto_ops::derive_secret_key(derivation, output_index, base, derived_key);
}
/* Generation and checking of a standard signature.
*/
inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
crypto_ops::generate_signature(prefix_hash, pub, sec, sig);
}
inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
return crypto_ops::check_signature(prefix_hash, pub, sig);
}
/* To send money to a key:
* * The sender generates an ephemeral key and includes it in transaction output.
* * To spend the money, the receiver generates a key image from it.
* * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature.
* To check the signature, it is necessary to collect all the keys that were used to generate it. To detect double spends, it is necessary to check that each key image is used at most once.
*/
inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
crypto_ops::generate_key_image(pub, sec, image);
}
inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
const public_key *const *pubs, std::size_t pubs_count,
const secret_key &sec, std::size_t sec_index,
signature *sig) {
crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig);
}
inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
const public_key *const *pubs, std::size_t pubs_count,
const signature *sig) {
return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig);
}
/* Variants with vector<const public_key *> parameters.
*/
inline void generate_ring_signature(const hash &prefix_hash, const key_image &image,
const std::vector<const public_key *> &pubs,
const secret_key &sec, std::size_t sec_index,
signature *sig) {
generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
}
inline bool check_ring_signature(const hash &prefix_hash, const key_image &image,
const std::vector<const public_key *> &pubs,
const signature *sig) {
return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig);
}
}
CRYPTO_MAKE_COMPARABLE(public_key)
CRYPTO_MAKE_HASHABLE(key_image)
CRYPTO_MAKE_COMPARABLE(signature)

View file

@ -0,0 +1,32 @@
#pragma once
#include <cstddef>
#include <cstring>
#include <functional>
#define CRYPTO_MAKE_COMPARABLE(type) \
namespace crypto { \
inline bool operator==(const type &_v1, const type &_v2) { \
return std::memcmp(&_v1, &_v2, sizeof(type)) == 0; \
} \
inline bool operator!=(const type &_v1, const type &_v2) { \
return std::memcmp(&_v1, &_v2, sizeof(type)) != 0; \
} \
}
#define CRYPTO_MAKE_HASHABLE(type) \
CRYPTO_MAKE_COMPARABLE(type) \
namespace crypto { \
static_assert(sizeof(std::size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \
inline std::size_t hash_value(const type &_v) { \
return reinterpret_cast<const std::size_t &>(_v); \
} \
} \
namespace std { \
template<> \
struct hash<crypto::type> { \
std::size_t operator()(const crypto::type &_v) const { \
return reinterpret_cast<const std::size_t &>(_v); \
} \
}; \
}

View file

@ -0,0 +1,44 @@
#pragma once
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "int-util.h"
#include "warnings.h"
//#include "crypto.h"
static inline void *padd(void *p, size_t i) {
return (char *) p + i;
}
static inline const void *cpadd(const void *p, size_t i) {
return (const char *) p + i;
}
static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t must be 4 or 8 bytes long");
static inline void place_length(uint8_t *buffer, size_t bufsize, size_t length) {
if (sizeof(size_t) == 4) {
*(uint32_t *) padd(buffer, bufsize - 4) = swap32be(length);
} else {
*(uint64_t *) padd(buffer, bufsize - 8) = swap64be(length);
}
}
#pragma pack(push, 1)
union hash_state {
uint8_t b[200];
uint64_t w[25];
};
#pragma pack(pop)
static_assert(sizeof(union hash_state) == 200, "Invalid structure size");
void hash_permutation(union hash_state *state);
enum {
HASH_SIZE = 32,
HASH_DATA_AREA = 136
};
//void cn_fast_hash(const void *data, size_t length, char *hash);

View file

@ -0,0 +1,28 @@
#pragma once
#if defined(__GNUC__)
#define INITIALIZER(name) __attribute__((constructor(101))) static void name(void)
#define FINALIZER(name) __attribute__((destructor(101))) static void name(void)
#define REGISTER_FINALIZER(name) ((void) 0)
#elif defined(_MSC_VER)
#include <assert.h>
#include <stdlib.h>
// http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc
// http://msdn.microsoft.com/en-us/library/bb918180.aspx
#pragma section(".CRT$XCT", read)
#define INITIALIZER(name) \
static void __cdecl name(void); \
__declspec(allocate(".CRT$XCT")) void (__cdecl *const _##name)(void) = &name; \
static void __cdecl name(void)
#define FINALIZER(name) \
static void __cdecl name(void)
#define REGISTER_FINALIZER(name) \
do { \
int _res = atexit(name); \
assert(_res == 0); \
} while (0);
#else
#error Unsupported compiler
#endif

View file

@ -0,0 +1,201 @@
#pragma once
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "param.h"
#if defined(_MSC_VER)
#include <stdlib.h>
static inline uint32_t rol32(uint32_t x, int r) {
static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers");
return _rotl(x, r);
}
static inline uint64_t rol64(uint64_t x, int r) {
return _rotl64(x, r);
}
#else
static inline uint32_t rol32(uint32_t x, int r) {
return (x << (r & 31)) | (x >> (-r & 31));
}
static inline uint64_t rol64(uint64_t x, int r) {
return (x << (r & 63)) | (x >> (-r & 63));
}
#endif
static inline uint64_t hi_dword(uint64_t val) {
return val >> 32;
}
static inline uint64_t lo_dword(uint64_t val) {
return val & 0xFFFFFFFF;
}
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) {
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
uint64_t a = hi_dword(multiplier);
uint64_t b = lo_dword(multiplier);
uint64_t c = hi_dword(multiplicand);
uint64_t d = lo_dword(multiplicand);
uint64_t ac = a * c;
uint64_t ad = a * d;
uint64_t bc = b * c;
uint64_t bd = b * d;
uint64_t adbc = ad + bc;
uint64_t adbc_carry = adbc < ad ? 1 : 0;
// multiplier * multiplicand = product_hi * 2^64 + product_lo
uint64_t product_lo = bd + (adbc << 32);
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
*product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
assert(ac <= *product_hi);
return product_lo;
}
static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) {
dividend |= ((uint64_t)*remainder) << 32;
*remainder = dividend % divisor;
return dividend / divisor;
}
// Long division with 2^32 base
static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) {
uint64_t dividend_dwords[4];
uint32_t remainder = 0;
dividend_dwords[3] = hi_dword(dividend_hi);
dividend_dwords[2] = lo_dword(dividend_hi);
dividend_dwords[1] = hi_dword(dividend_lo);
dividend_dwords[0] = lo_dword(dividend_lo);
*quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32;
*quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder);
*quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32;
*quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder);
return remainder;
}
#define IDENT32(x) ((uint32_t) (x))
#define IDENT64(x) ((uint64_t) (x))
#define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \
(((uint32_t) (x) & 0x0000ff00) << 8) | \
(((uint32_t) (x) & 0x00ff0000) >> 8) | \
(((uint32_t) (x) & 0xff000000) >> 24))
#define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \
(((uint64_t) (x) & 0x000000000000ff00) << 40) | \
(((uint64_t) (x) & 0x0000000000ff0000) << 24) | \
(((uint64_t) (x) & 0x00000000ff000000) << 8) | \
(((uint64_t) (x) & 0x000000ff00000000) >> 8) | \
(((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \
(((uint64_t) (x) & 0x00ff000000000000) >> 40) | \
(((uint64_t) (x) & 0xff00000000000000) >> 56))
static inline uint32_t ident32(uint32_t x) { return x; }
static inline uint64_t ident64(uint64_t x) { return x; }
static inline uint32_t swap32(uint32_t x) {
x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
return (x << 16) | (x >> 16);
}
static inline uint64_t swap64(uint64_t x) {
x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8);
x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16);
return (x << 32) | (x >> 32);
}
#if defined(__GNUC__)
#define UNUSED __attribute__((unused))
#else
#define UNUSED
#endif
static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { }
#undef UNUSED
static inline void mem_inplace_swap32(void *mem, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]);
}
}
static inline void mem_inplace_swap64(void *mem, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]);
}
}
static inline void memcpy_ident32(void *dst, const void *src, size_t n) {
memcpy(dst, src, 4 * n);
}
static inline void memcpy_ident64(void *dst, const void *src, size_t n) {
memcpy(dst, src, 8 * n);
}
static inline void memcpy_swap32(void *dst, const void *src, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]);
}
}
static inline void memcpy_swap64(void *dst, const void *src, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]);
}
}
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled");
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#define SWAP32LE IDENT32
#define SWAP32BE SWAP32
#define swap32le ident32
#define swap32be swap32
#define mem_inplace_swap32le mem_inplace_ident
#define mem_inplace_swap32be mem_inplace_swap32
#define memcpy_swap32le memcpy_ident32
#define memcpy_swap32be memcpy_swap32
#define SWAP64LE IDENT64
#define SWAP64BE SWAP64
#define swap64le ident64
#define swap64be swap64
#define mem_inplace_swap64le mem_inplace_ident
#define mem_inplace_swap64be mem_inplace_swap64
#define memcpy_swap64le memcpy_ident64
#define memcpy_swap64be memcpy_swap64
#endif
#if BYTE_ORDER == BIG_ENDIAN
#define SWAP32BE IDENT32
#define SWAP32LE SWAP32
#define swap32be ident32
#define swap32le swap32
#define mem_inplace_swap32be mem_inplace_ident
#define mem_inplace_swap32le mem_inplace_swap32
#define memcpy_swap32be memcpy_ident32
#define memcpy_swap32le memcpy_swap32
#define SWAP64BE IDENT64
#define SWAP64LE SWAP64
#define swap64be ident64
#define swap64le swap64
#define mem_inplace_swap64be mem_inplace_ident
#define mem_inplace_swap64le mem_inplace_swap64
#define memcpy_swap64be memcpy_ident64
#define memcpy_swap64le memcpy_swap64
#endif

115
source-code/RingCT/keccak.c Normal file
View file

@ -0,0 +1,115 @@
// keccak.c
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
// A baseline Keccak (3rd round) implementation.
//
#include "hash-ops.h"
#include "keccak.h"
const uint64_t keccakf_rndc[24] =
{
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
const int keccakf_rotc[24] =
{
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
};
const int keccakf_piln[24] =
{
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
};
// update the state with given number of rounds
void keccakf(uint64_t st[25], int rounds)
{
int i, j, round;
uint64_t t, bc[5];
for (round = 0; round < rounds; round++) {
// Theta
for (i = 0; i < 5; i++)
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
for (i = 0; i < 5; i++) {
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
for (j = 0; j < 25; j += 5)
st[j + i] ^= t;
}
// Rho Pi
t = st[1];
for (i = 0; i < 24; i++) {
j = keccakf_piln[i];
bc[0] = st[j];
st[j] = ROTL64(t, keccakf_rotc[i]);
t = bc[0];
}
// Chi
for (j = 0; j < 25; j += 5) {
for (i = 0; i < 5; i++)
bc[i] = st[j + i];
for (i = 0; i < 5; i++)
st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
}
// Iota
st[0] ^= keccakf_rndc[round];
}
}
// compute a keccak hash (md) of given byte length from "in"
typedef uint64_t state_t[25];
//Changed inlen to size_t (s.n. MRL labs)
int keccak(const uint8_t *in, std::size_t inlen, uint8_t *md, int mdlen)
{
state_t st;
uint8_t temp[144];
std::size_t i, rsiz, rsizw;
rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen;
rsizw = rsiz / 8;
memset(st, 0, sizeof(st));
for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) {
for (i = 0; i < rsizw; i++)
st[i] ^= ((uint64_t *) in)[i];
keccakf(st, KECCAK_ROUNDS);
}
// last block and padding
memcpy(temp, in, inlen);
temp[inlen++] = 1;
memset(temp + inlen, 0, rsiz - inlen);
temp[rsiz - 1] |= 0x80;
for (i = 0; i < rsizw; i++)
st[i] ^= ((uint64_t *) temp)[i];
keccakf(st, KECCAK_ROUNDS);
memcpy(md, st, mdlen);
return 0;
}
//Changed inlen to size_t (s.n. MRL labs)
void keccak1600(const uint8_t *in, std::size_t inlen, uint8_t *md)
{
keccak(in, inlen, md, sizeof(state_t));
}

View file

@ -0,0 +1,29 @@
// keccak.h
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
#ifndef keccak_H
#define keccak_H
#include <cstddef>
#include <stdint.h>
#include <string.h>
#ifndef KECCAK_ROUNDS
#define KECCAK_ROUNDS 24
#endif
#ifndef ROTL64
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
#endif
//Changed inlen to size_t (s.n. MRL labs)
// compute a keccak hash (md) of given byte length from "in"
int keccak(const uint8_t *in, std::size_t inlen, uint8_t *md, int mdlen);
// update the state
void keccakf(uint64_t st[25], int norounds);
//Changed inlen to size_t (s.n. MRL labs)
void keccak1600(const uint8_t *in, std::size_t inlen, uint8_t *md);
#endif

View file

@ -0,0 +1,36 @@
// Copyright (c) 2014-2015, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#define LITTLE_ENDIAN 1234
#define BIG_ENDIAN 4321
#define PDP_ENDIAN 3412
#define BYTE_ORDER LITTLE_ENDIAN

114
source-code/RingCT/random.c Normal file
View file

@ -0,0 +1,114 @@
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include "hash-ops.h"
#include "initializer.h"
#include "random.h"
static void generate_system_random_bytes(size_t n, void *result);
#include <windows.h>
#include <wincrypt.h>
static void generate_system_random_bytes(size_t n, void *result) {
HCRYPTPROV prov;
#define must_succeed(x) do if (!(x)) assert(0); while (0)
must_succeed(CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT));
must_succeed(CryptGenRandom(prov, (DWORD)n, result));
must_succeed(CryptReleaseContext(prov, 0));
#undef must_succeed
}
//uncomment for nix
/*
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
static void generate_system_random_bytes(size_t n, void *result) {
int fd;
if ((fd = open("/dev/urandom", O_RDONLY | O_NOCTTY | O_CLOEXEC)) < 0) {
err(EXIT_FAILURE, "open /dev/urandom");
}
for (;;) {
ssize_t res = read(fd, result, n);
if ((size_t) res == n) {
break;
}
if (res < 0) {
if (errno != EINTR) {
err(EXIT_FAILURE, "read /dev/urandom");
}
} else if (res == 0) {
errx(EXIT_FAILURE, "read /dev/urandom: end of file");
} else {
result = padd(result, (size_t) res);
n -= (size_t) res;
}
}
if (close(fd) < 0) {
err(EXIT_FAILURE, "close /dev/urandom");
}
}
#endif
*/
static union hash_state state;
#if !defined(NDEBUG)
static volatile int curstate; /* To catch thread safety problems. */
#endif
FINALIZER(deinit_random) {
#if !defined(NDEBUG)
assert(curstate == 1);
curstate = 0;
#endif
memset(&state, 0, sizeof(union hash_state));
}
INITIALIZER(init_random) {
generate_system_random_bytes(32, &state);
REGISTER_FINALIZER(deinit_random);
#if !defined(NDEBUG)
assert(curstate == 0);
curstate = 1;
#endif
}
void generate_random_bytes(size_t n, void *result) {
#if !defined(NDEBUG)
assert(curstate == 1);
curstate = 2;
#endif
if (n == 0) {
#if !defined(NDEBUG)
assert(curstate == 2);
curstate = 1;
#endif
return;
}
for (;;) {
hash_permutation(&state);
if (n <= HASH_DATA_AREA) {
memcpy(result, &state, n);
#if !defined(NDEBUG)
assert(curstate == 2);
curstate = 1;
#endif
return;
} else {
memcpy(result, &state, HASH_DATA_AREA);
result = padd(result, HASH_DATA_AREA);
n -= HASH_DATA_AREA;
}
}
}

View file

@ -0,0 +1,11 @@
#pragma once
#include <stddef.h>
#include "hash-ops.h" //needed for hash_permutation
#include "keccak.h"
void generate_random_bytes(size_t n, void *result);
inline void hash_permutation(union hash_state *state) {
keccakf((uint64_t*)state, 24);
} //brought over from hash.h

View file

@ -0,0 +1,37 @@
// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rctMSig.h"
using namespace crypto;
using namespace std;
namespace rct {
}

View file

@ -0,0 +1,68 @@
// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#define DBG
#ifndef RCTSIGS_H
#define RCTSIGS_H
#include <cstddef>
#include <mutex>
#include <vector>
#include <tuple>
#include "generic-ops.h"
#include "crypto-ops.h"
#include "random.h"
#include "keccak.h"
#include "crypto.h"
#include "rctTypes.h"
#include "rctOps.h"
using namespace std;
using namespace crypto;
namespace rct {
int i;
//rctSig genRMS(ctkeyV & inSk, ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> amounts, const int mixin);
}
#endif

View file

@ -0,0 +1,395 @@
// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rctOps.h"
using namespace crypto;
using namespace std;
namespace rct {
//Various key initialization functions
//Creates a zero scalar
void zero(key &zero) {
int i = 0;
for (i = 0; i < 32; i++) {
zero[i] = (unsigned char)(0x00);
}
}
//Creates a zero scalar
key zero() {
return{ {0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } };
}
//Creates a zero elliptic curve point
void identity(key &Id) {
int i = 0;
Id[0] = (unsigned char)(0x01);
for (i = 1; i < 32; i++) {
Id[i] = (unsigned char)(0x00);
}
}
//Creates a zero elliptic curve point
key identity() {
key Id;
int i = 0;
Id[0] = (unsigned char)(0x01);
for (i = 1; i < 32; i++) {
Id[i] = (unsigned char)(0x00);
}
return Id;
}
//copies a scalar or point
void copy(key &AA, const key &A) {
int i = 0;
for (i = 0; i < 32; i++) {
AA[i] = A[i];
}
}
//copies a scalar or point
key copy(const key &A) {
int i = 0;
key AA;
for (i = 0; i < 32; i++) {
AA[i] = A[i];
}
return AA;
}
//initializes a key matrix;
//first parameter is rows,
//second is columns
keyM keyMInit(int rows, int cols) {
keyM rv(cols);
int i = 0;
for (i = 0 ; i < cols ; i++) {
rv[i] = keyV(rows);
}
return rv;
}
//Various key generation functions
//generates a random scalar which can be used as a secret key or mask
void skGen(key &sk) {
unsigned char tmp[64];
generate_random_bytes(64, tmp);
sc_reduce(tmp);
memcpy(sk.bytes, tmp, 32);
}
//generates a random scalar which can be used as a secret key or mask
key skGen() {
unsigned char tmp[64];
generate_random_bytes(64, tmp);
sc_reduce(tmp);
key sk;
memcpy(sk.bytes, tmp, 32);
return sk;
}
//Generates a vector of secret key
//Mainly used in testing
keyV skvGen(int rows ) {
keyV rv(rows);
int i = 0;
for (i = 0 ; i < rows ; i++) {
skGen(rv[i]);
}
return rv;
}
//generates a random curve point (for testing)
key pkGen() {
key sk = skGen();
key pk = scalarmultBase(sk);
return pk;
}
//generates a random secret and corresponding public key
void skpkGen(key &sk, key &pk) {
skGen(sk);
scalarmultBase(pk, sk);
}
//generates a random secret and corresponding public key
tuple<key, key> skpkGen() {
key sk = skGen();
key pk = scalarmultBase(sk);
return make_tuple(sk, pk);
}
//generates a <secret , public> / Pedersen commitment to the amount
tuple<ctkey, ctkey> ctskpkGen(xmr_amount amount) {
ctkey sk, pk;
skpkGen(sk.dest, pk.dest);
skpkGen(sk.mask, pk.mask);
key am = d2h(amount);
key aH = scalarmultH(am);
addKeys(pk.mask, pk.mask, aH);
return make_tuple(sk, pk);
}
//generates a <secret , public> / Pedersen commitment but takes bH as input
tuple<ctkey, ctkey> ctskpkGen(key bH) {
ctkey sk, pk;
skpkGen(sk.dest, pk.dest);
skpkGen(sk.mask, pk.mask);
//key am = d2h(amount);
//key aH = scalarmultH(am);
addKeys(pk.mask, pk.mask, bH);
return make_tuple(sk, pk);
}
//generates a random uint long long
xmr_amount randXmrAmount(xmr_amount upperlimit) {
return h2d(skGen()) % (upperlimit);
}
//Scalar multiplications of curve points
//does a * G where a is a scalar and G is the curve basepoint
void scalarmultBase(key &aG,const key &a) {
ge_p3 point;
sc_reduce32copy(aG.bytes, a.bytes); //do this beforehand!
ge_scalarmult_base(&point, aG.bytes);
ge_p3_tobytes(aG.bytes, &point);
}
//does a * G where a is a scalar and G is the curve basepoint
key scalarmultBase(const key & a) {
ge_p3 point;
key aG;
sc_reduce32copy(aG.bytes, a.bytes); //do this beforehand
ge_scalarmult_base(&point, aG.bytes);
ge_p3_tobytes(aG.bytes, &point);
return aG;
}
//does a * P where a is a scalar and P is an arbitrary point
void scalarmultKey(key & aP, const key &P, const key &a) {
ge_p3 A;
ge_p2 R;
ge_frombytes_vartime(&A, P.bytes);
ge_scalarmult(&R, a.bytes, &A);
ge_tobytes(aP.bytes, &R);
}
//does a * P where a is a scalar and P is an arbitrary point
key scalarmultKey(const key & P, const key & a) {
ge_p3 A;
ge_p2 R;
ge_frombytes_vartime(&A, P.bytes);
ge_scalarmult(&R, a.bytes, &A);
key aP;
ge_tobytes(aP.bytes, &R);
return aP;
}
//Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint
key scalarmultH(const key & a) {
ge_p3 A;
ge_p2 R;
key Htmp = { {0x8b, 0x65, 0x59, 0x70, 0x15, 0x37, 0x99, 0xaf, 0x2a, 0xea, 0xdc, 0x9f, 0xf1, 0xad, 0xd0, 0xea, 0x6c, 0x72, 0x51, 0xd5, 0x41, 0x54, 0xcf, 0xa9, 0x2c, 0x17, 0x3a, 0x0d, 0xd3, 0x9c, 0x1f, 0x94} };
ge_frombytes_vartime(&A, Htmp.bytes);
ge_scalarmult(&R, a.bytes, &A);
key aP;
ge_tobytes(aP.bytes, &R);
return aP;
}
//Curve addition / subtractions
//for curve points: AB = A + B
void addKeys(key &AB, const key &A, const key &B) {
ge_p3 B2, A2;
ge_frombytes_vartime(&B2, B.bytes);
ge_frombytes_vartime(&A2, A.bytes);
ge_cached tmp2;
ge_p3_to_cached(&tmp2, &B2);
ge_p1p1 tmp3;
ge_add(&tmp3, &A2, &tmp2);
key rv;
ge_p1p1_to_p3(&A2, &tmp3);
ge_p3_tobytes(AB.bytes, &A2);
}
//addKeys1
//aGB = aG + B where a is a scalar, G is the basepoint, and B is a point
void addKeys1(key &aGB, const key &a, const key & B) {
key aG = scalarmultBase(a);
addKeys(aGB, aG, B);
}
//addKeys2
//aGbB = aG + bB where a, b are scalars, G is the basepoint and B is a point
void addKeys2(key &aGbB, const key &a, const key &b, const key & B) {
ge_p2 rv;
ge_p3 B2;
ge_frombytes_vartime(&B2, B.bytes);
ge_double_scalarmult_base_vartime(&rv, b.bytes, &B2, a.bytes);
ge_tobytes(aGbB.bytes, &rv);
}
//Does some precomputation to make addKeys3 more efficient
// input B a curve point and output a ge_dsmp which has precomputation applied
void precomp(ge_dsmp rv, const key & B) {
ge_p3 B2;
ge_frombytes_vartime(&B2, B.bytes);
ge_dsm_precomp(rv, &B2);
}
//addKeys3
//aAbB = a*A + b*B where a, b are scalars, A, B are curve points
//B must be input after applying "precomp"
void addKeys3(key &aAbB, const key &a, const key &A, const key &b, const ge_dsmp B) {
ge_p2 rv;
ge_p3 A2;
ge_frombytes_vartime(&A2, A.bytes);
ge_double_scalarmult_precomp_vartime(&rv, a.bytes, &A2, b.bytes, B);
ge_tobytes(aAbB.bytes, &rv);
}
//subtract Keys (subtracts curve points)
//AB = A - B where A, B are curve points
void subKeys(key & AB, const key &A, const key &B) {
ge_p3 B2, A2;
ge_frombytes_vartime(&B2, B.bytes);
ge_frombytes_vartime(&A2, A.bytes);
ge_cached tmp2;
ge_p3_to_cached(&tmp2, &B2);
ge_p1p1 tmp3;
ge_sub(&tmp3, &A2, &tmp2);
ge_p1p1_to_p3(&A2, &tmp3);
ge_p3_tobytes(AB.bytes, &A2);
}
//checks if A, B are equal as curve points
//without doing curve operations
bool equalKeys(key & a, key & b) {
key eqk;
sc_sub(eqk.bytes, cn_fast_hash(a).bytes, cn_fast_hash(b).bytes);
if (sc_isnonzero(eqk.bytes) ) {
DP("eq bytes");
DP(eqk);
return false;
}
return true;
}
//Hashing - cn_fast_hash
//be careful these are also in crypto namespace
//cn_fast_hash for arbitrary multiples of 32 bytes
void cn_fast_hash(key &hash, const void * data, const std::size_t l) {
uint8_t md2[32];
int j = 0;
keccak((uint8_t *)data, l, md2, 32);
for (j = 0; j < 32; j++) {
hash[j] = (unsigned char)md2[j];
}
sc_reduce32(hash.bytes);
}
//cn_fast_hash for a 32 byte key
void cn_fast_hash(key & hash, const key & in) {
uint8_t md2[32];
int j = 0;
keccak((uint8_t *)in.bytes, 32, md2, 32);
for (j = 0; j < 32; j++) {
hash[j] = (unsigned char)md2[j];
}
sc_reduce32(hash.bytes);
}
//cn_fast_hash for a 32 byte key
key cn_fast_hash(const key & in) {
uint8_t md2[32];
int j = 0;
key hash;
keccak((uint8_t *)in.bytes, 32, md2, 32);
for (j = 0; j < 32; j++) {
hash[j] = (unsigned char)md2[j];
}
sc_reduce32(hash.bytes);
return hash;
}
//returns cn_fast_hash(input) * G where G is the basepoint
key hashToPoint(const key & in) {
return scalarmultBase(cn_fast_hash(in));
}
//returns cn_fast_hash(input) * G where G is the basepoint
void hashToPoint(key & out, const key & in) {
scalarmultBase(out, cn_fast_hash(in));
}
//sums a vector of curve points (for scalars use sc_add)
void sumKeys(key & Csum, const keyV & Cis) {
identity(Csum);
int i = 0;
for (i = 0; i < Cis.size(); i++) {
addKeys(Csum, Csum, Cis[i]);
}
}
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH
void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk) {
key esk;
//compute shared secret
skpkGen(esk, unmasked.senderPk);
key sharedSec1 = cn_fast_hash(scalarmultKey(receiverPk, esk));
key sharedSec2 = cn_fast_hash(sharedSec1);
//encode
sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes);
sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec1.bytes);
}
void ecdhDecode(ecdhTuple & masked, const key & receiverSk) {
//compute shared secret
key sharedSec1 = cn_fast_hash(scalarmultKey(masked.senderPk, receiverSk));
key sharedSec2 = cn_fast_hash(sharedSec1);
//encode
sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes);
sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec1.bytes);
}
}

144
source-code/RingCT/rctOps.h Normal file
View file

@ -0,0 +1,144 @@
#define DBG
// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#ifndef RCTOPS_H
#define RCTOPS_H
#include <cstddef>
#include <mutex>
#include <vector>
#include <tuple>
#include "generic-ops.h"
#include "crypto-ops.h"
#include "random.h"
#include "keccak.h"
#include "crypto.h"
#include "rctTypes.h"
using namespace std;
using namespace crypto;
namespace rct {
//Various key initialization functions
//Creates a zero scalar
key zero();
void zero(key &z);
//Creates a zero elliptic curve point
key identity();
void identity(key &Id);
//copies a scalar or point
void copy(key &AA, const key &A);
key copy(const key & AA);
//initializes a key matrix;
//first parameter is rows,
//second is columns
keyM keyMInit(int, int);
//Various key generation functions
//generates a random scalar which can be used as a secret key or mask
key skGen();
void skGen(key &);
//generates a vector of secret keys of size "int"
keyV skvGen(int );
//generates a random curve point (for testing)
key pkGen();
//generates a random secret and corresponding public key
void skpkGen(key &sk, key &pk);
tuple<key, key> skpkGen();
//generates a <secret , public> / Pedersen commitment to the amount
tuple<ctkey, ctkey> ctskpkGen(xmr_amount amount);
//this one is mainly for testing, can take arbitrary amounts..
tuple<ctkey, ctkey> ctskpkGen(key bH);
//generates a random uint long long
xmr_amount randXmrAmount(xmr_amount upperlimit);
//Scalar multiplications of curve points
//does a * G where a is a scalar and G is the curve basepoint
void scalarmultBase(key & aG, const key &a);
key scalarmultBase(const key & a);
//does a * P where a is a scalar and P is an arbitrary point
void scalarmultKey(key &aP, const key &P, const key &a);
key scalarmultKey(const key &P, const key &a);
//Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint
key scalarmultH(const key & a);
//Curve addition / subtractions
//for curve points: AB = A + B
void addKeys(key &AB, const key &A, const key &B);
//aGB = aG + B where a is a scalar, G is the basepoint, and B is a point
void addKeys1(key &aGB, const key &a, const key & B);
//aGbB = aG + bB where a, b are scalars, G is the basepoint and B is a point
void addKeys2(key &aGbB, const key &a, const key &b, const key &B);
//Does some precomputation to make addKeys3 more efficient
// input B a curve point and output a ge_dsmp which has precomputation applied
void precomp(ge_dsmp rv, const key &B);
//aAbB = a*A + b*B where a, b are scalars, A, B are curve points
//B must be input after applying "precomp"
void addKeys3(key &aAbB, const key &a, const key &A, const key &b, const ge_dsmp B);
//AB = A - B where A, B are curve points
void subKeys(key &AB, const key &A, const key &B);
//checks if A, B are equal as curve points
bool equalKeys(key & A, key & B);
//Hashing - cn_fast_hash
//be careful these are also in crypto namespace
//cn_fast_hash for arbitrary multiples of 32 bytes
void cn_fast_hash(key &hash, const void * data, const size_t l);
//cn_fast_hash for a 32 byte key
void cn_fast_hash(key &hash, const key &in);
//cn_fast_hash for a 32 byte key
key cn_fast_hash(const key &in);
//returns cn_fast_hash(input) * G where G is the basepoint
key hashToPoint(const key &in);
void hashToPoint(key &out, const key &in);
//sums a vector of curve points (for scalars use sc_add)
void sumKeys(key & Csum, const key &Cis);
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH
void ecdhEncode(ecdhTuple & unmasked, const key & receiverPk);
void ecdhDecode(ecdhTuple & masked, const key & receiverSk);
}
#endif /* RCTOPS_H */

View file

@ -0,0 +1,540 @@
// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rctSigs.h"
using namespace crypto;
using namespace std;
namespace rct {
//Schnorr Non-linkable
//Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2
//Ver Verifies that signer knows an "x" such that xG = one of P1 or P2
//These are called in the below ASNL sig generation
void GenSchnorrNonLinkable(key & L1, key & s1, key & s2, const key & x, const key & P1, const key & P2, int index) {
key c1, c2, L2;
key a = skGen();
if (index == 0) {
scalarmultBase(L1, a);
skGen(s2);
cn_fast_hash(c2, L1);
addKeys2(L2, s2, c2, P2);
cn_fast_hash(c1, L2);
sc_mulsub(s1.bytes, x.bytes, c1.bytes, a.bytes);
}
if (index == 1) {
scalarmultBase(L2, a);
skGen(s1);
cn_fast_hash(c1, L2);
addKeys2(L1, s1, c1, P1);
cn_fast_hash(c2, L1);
sc_mulsub(s2.bytes, x.bytes, c2.bytes, a.bytes);
}
}
//Schnorr Non-linkable
//Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2
//Ver Verifies that signer knows an "x" such that xG = one of P1 or P2
//These are called in the below ASNL sig generation
bool VerSchnorrNonLinkable(const key & P1, const key & P2, const key & L1, const key & s1, const key & s2) {
key c2, L2, c1, L1p, cc;
cn_fast_hash(c2, L1);
addKeys2(L2, s2, c2, P2);
cn_fast_hash(c1, L2);
addKeys2(L1p, s1, c1, P1);
sc_sub(cc.bytes, L1.bytes, L1p.bytes);
return sc_isnonzero(cc.bytes) == 0;
}
//Aggregate Schnorr Non-linkable Ring Signature (ASNL)
// c.f. http://eprint.iacr.org/2015/1098 section 5.
// These are used in range proofs (alternatively Borromean could be used)
// Gen gives a signature which proves the signer knows, for each i,
// an x[i] such that x[i]G = one of P1[i] or P2[i]
// Ver Verifies the signer knows a key for one of P1[i], P2[i] at each i
asnlSig GenASNL(key64 x, key64 P1, key64 P2, bits indices) {
DP("Generating Aggregate Schnorr Non-linkable Ring Signature\n");
key64 s1;
int j = 0;
asnlSig rv;
rv.s = zero();
for (j = 0; j < ATOMS; j++) {
//void GenSchnorrNonLinkable(Bytes L1, Bytes s1, Bytes s2, const Bytes x, const Bytes P1,const Bytes P2, int index) {
GenSchnorrNonLinkable(rv.L1[j], s1[j], rv.s2[j], x[j], P1[j], P2[j], indices[j]);
sc_add(rv.s.bytes, rv.s.bytes, s1[j].bytes);
}
return rv;
}
//Aggregate Schnorr Non-linkable Ring Signature (ASNL)
// c.f. http://eprint.iacr.org/2015/1098 section 5.
// These are used in range proofs (alternatively Borromean could be used)
// Gen gives a signature which proves the signer knows, for each i,
// an x[i] such that x[i]G = one of P1[i] or P2[i]
// Ver Verifies the signer knows a key for one of P1[i], P2[i] at each i
bool VerASNL(key64 P1, key64 P2, asnlSig &as) {
DP("Verifying Aggregate Schnorr Non-linkable Ring Signature\n");
key LHS = identity();
key RHS = scalarmultBase(as.s);
key c2, L2, c1;
int j = 0;
for (j = 0; j < ATOMS; j++) {
cn_fast_hash(c2, as.L1[j]);
addKeys2(L2, as.s2[j], c2, P2[j]);
addKeys(LHS, LHS, as.L1[j]);
cn_fast_hash(c1, L2);
addKeys(RHS, RHS, scalarmultKey(P1[j], c1));
}
key cc;
sc_sub(cc.bytes, LHS.bytes, RHS.bytes);
return sc_isnonzero(cc.bytes) == 0;
}
//Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
//These are aka MG signatutes in earlier drafts of the ring ct paper
// c.f. http://eprint.iacr.org/2015/1098 section 2.
// keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
keyV keyImageV(const keyV &xx) {
keyV II(xx.size());
int i = 0;
for (i = 0; i < xx.size(); i++) {
II[i] = scalarmultKey(hashToPoint(scalarmultBase(xx[i])), xx[i]);
}
return II;
}
/*
keyV skvGen(int n) {
keyV rv(n);
int i = 0;
for (i = 0; i < n; i++) {
skGen(rv[i]);
}
return rv;
}
*/
//Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
//These are aka MG signatutes in earlier drafts of the ring ct paper
// c.f. http://eprint.iacr.org/2015/1098 section 2.
// keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
mgSig MLSAG_Gen(const keyM & pk, const keyV & xx, const int index) {
mgSig rv;
int rows = pk[0].size();
int cols = pk.size();
if (cols < 2) {
printf("Error! What is c if cols = 1!");
}
int i = 0, j = 0;
keyV c(cols);
keyV alpha = skvGen(rows);
rv.II = keyImageV(xx);
DP(rv.II);
vector<ge_dsmp> Ip(rows);
keyM L(cols, rv.II);
keyM R(cols, rv.II);
rv.ss = keyM(cols, rv.II);
keyV Hi(rows);
for (i = 0; i < rows; i++) {
L[index][i] = scalarmultBase(alpha[i]);
hashToPoint(Hi[i], pk[index][i]);
R[index][i] = scalarmultKey(Hi[i], alpha[i]);
precomp(Ip[i], rv.II[i]);
}
char * m1 = (char *)malloc(32 * rows * (cols + 2));
//vector<char> m1(32 * rows * (cols + 2));
for (i = 0; i < cols; i++) {
for (j = 0; j < rows; j++) {
memcpy(m1 + rows * 32 * i + (32 * j), pk[i][j].bytes, 32);
}
}
int oldi = index;
i = (index + 1) % cols;
for (j = 0; j < rows; j++) {
memcpy(m1 + rows * 32 * cols + (32 * j), L[oldi][j].bytes, 32);
memcpy(m1 + rows * 32 * (cols + 1) + (32 * j), R[oldi][j].bytes, 32);
}
while (i != index) {
cn_fast_hash(c[i], m1, 32 * rows * (cols + 2));
rv.ss[i] = skvGen(rows);
for (j = 0; j < rows; j++) {
addKeys2(L[i][j], rv.ss[i][j], c[i], pk[i][j]);
hashToPoint(Hi[j], pk[i][j]);
addKeys3(R[i][j], rv.ss[i][j], Hi[j], c[i], Ip[j]);
}
oldi = i;
i = (i + 1) % cols;
for (j = 0; j < rows; j++) {
memcpy(m1 + rows * 32 * cols + (32 * j), L[oldi][j].bytes, 32);
memcpy(m1 + rows * 32 * (cols + 1) + (32 * j), R[oldi][j].bytes, 32);
}
}
cn_fast_hash(c[index], m1, 32 * rows * (cols + 2));
for (j = 0; j < rows; j++) {
sc_mulsub(rv.ss[index][j].bytes, c[index].bytes, xx[j].bytes, alpha[j].bytes);
}
memcpy(rv.cc.bytes, c[0].bytes, 32);
free(m1);
return rv;
}
//Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
//These are aka MG signatutes in earlier drafts of the ring ct paper
// c.f. http://eprint.iacr.org/2015/1098 section 2.
// keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
bool MLSAG_Ver(keyM &pk, mgSig &sig) {
int rows = pk[0].size();
int cols = pk.size();
if (cols < 2) {
printf("Error! What is c if cols = 1!");
}
DP("Verifying MG sig");
keyV c(cols + 1);
memcpy(c[0].bytes, sig.cc.bytes, 32);
vector<ge_dsmp> Ip(rows);
keyM L(cols, pk[0]);
keyM R(cols, pk[0]);
int i = 0, oldi = 0, j = 0;
keyV Hi(rows);
for (i = 0; i < rows; i++) {
precomp(Ip[i], sig.II[i]);
}
i = 0;
char * m1 = (char *)malloc(32 * rows * (cols + 2));
//vector<char> m1(32 * rows * (cols + 2));
for (i = 0; i < cols; i++) {
for (j = 0; j < rows; j++) {
memcpy(m1 + rows * 32 * i + (32 * j), pk[i][j].bytes, 32);
}
}
i = 0;
while (i < cols) {
for (j = 0; j < rows; j++) {
addKeys2(L[i][j], sig.ss[i][j], c[i], pk[i][j]);
hashToPoint(Hi[j], pk[i][j]);
addKeys3(R[i][j], sig.ss[i][j], Hi[j], c[i], Ip[j]);
}
oldi = i;
i = (i + 1);
for (j = 0; j < rows; j++) {
memcpy(m1 + rows * 32 * cols + (32 * j), L[oldi][j].bytes, 32);
memcpy(m1 + rows * 32 * (cols + 1) + (32 * j), R[oldi][j].bytes, 32);
}
cn_fast_hash(c[i], m1, 32 * rows * (cols + 2));
}
key cc;
sc_sub(cc.bytes, c[0].bytes, c[cols].bytes);
free(m1);
return sc_isnonzero(cc.bytes) == 0;
}
//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^64]
// 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
rangeSig proveRange(key & C, key & mask, const xmr_amount & amount) {
sc_0(mask.bytes);
identity(C);
bits b;
d2b(b, amount);
rangeSig sig;
key64 ai;
key64 CiH;
int i = 0;
for (i = 0; i < ATOMS; i++) {
sc_0(ai[i].bytes);
if (b[i] == 0) {
scalarmultBase(sig.Ci[i], ai[i]);
}
if (b[i] == 1) {
addKeys1(sig.Ci[i], ai[i], H2[i]);
}
subKeys(CiH[i], sig.Ci[i], H2[i]);
sc_add(mask.bytes, mask.bytes, ai[i].bytes);
addKeys(C, C, sig.Ci[i]);
}
sig.asig = GenASNL(ai, sig.Ci, CiH, b);
return sig;
}
//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^64]
// 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
bool verRange(key & C, rangeSig & as) {
key64 CiH;
int i = 0;
key Ctmp = identity();
for (i = 0; i < 64; i++) {
subKeys(CiH[i], as.Ci[i], H2[i]);
addKeys(Ctmp, Ctmp, as.Ci[i]);
}
bool reb = equalKeys(C, Ctmp);
DP("is sum Ci = C:");
DP(reb);
bool rab = VerASNL(as.Ci, CiH, as.asig);
DP("Is in range?"); DP(rab);
return (reb && rab);
}
//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
mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const ctkeyV &outSk, const ctkeyV & outPk, int index) {
mgSig mg;
//setup vars
int rows = pubs[0].size();
int cols = pubs.size();
keyV sk(rows + 1);
keyV tmp(rows + 1);
int i = 0, j = 0;
for (i = 0; i < rows + 1; i++) {
sc_0(sk[i].bytes);
identity(tmp[i]);
}
keyM M(cols, tmp);
//create the matrix to mg sig
for (i = 0; i < cols; i++) {
M[i][rows] = identity();
for (j = 0; j < rows; j++) {
M[i][j] = pubs[i][j].dest;
addKeys(M[i][rows], M[i][rows], pubs[i][j].mask);
}
}
sc_0(sk[rows].bytes);
for (j = 0; j < rows; j++) {
sk[j] = copy(inSk[j].dest);
sc_add(sk[rows].bytes, sk[rows].bytes, inSk[j].mask.bytes);
}
for (i = 0; i < cols; i++) {
for (j = 0; j < outPk.size(); j++) {
subKeys(M[i][rows], M[i][rows], outPk[j].mask);
}
}
for (j = 0; j < outPk.size(); j++) {
sc_sub(sk[rows].bytes, sk[rows].bytes, outSk[j].mask.bytes);
}
return MLSAG_Gen(M, sk, index);
}
//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
bool verRctMG(mgSig mg, ctkeyM & pubs, ctkeyV & outPk) {
//setup vars
int rows = pubs[0].size();
int cols = pubs.size();
keyV tmp(rows + 1);
int i = 0, j = 0;
for (i = 0; i < rows + 1; i++) {
identity(tmp[i]);
}
keyM M(cols, tmp);
//create the matrix to mg sig
for (j = 0; j < rows; j++) {
for (i = 0; i < cols; i++) {
M[i][j] = pubs[i][j].dest;
addKeys(M[i][rows], M[i][rows], pubs[i][j].mask);
}
}
for (j = 0; j < outPk.size(); j++) {
for (i = 0; i < cols; i++) {
subKeys(M[i][rows], M[i][rows], outPk[j].mask);
}
}
return MLSAG_Ver(M, mg);
}
//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).
void getKeyFromBlockchain(ctkey & a, size_t reference_index) {
a.mask = pkGen();
a.dest = pkGen();
}
//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).
tuple<ctkeyM, xmr_amount> populateFromBlockchain(ctkeyV inPk, int mixin) {
int rows = inPk.size();
ctkeyM rv(mixin, inPk);
int index = randXmrAmount(mixin);
int i = 0, j = 0;
for (i = 0; i < mixin; i++) {
if (i != index) {
for (j = 0; j < rows; j++) {
getKeyFromBlockchain(rv[i][j], (size_t)randXmrAmount);
}
}
}
return make_tuple(rv, index);
}
//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
rctSig genRct(ctkeyV & inSk, ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> amounts, const int mixin) {
rctSig rv;
rv.outPk.resize(destinations.size());
rv.rangeSigs.resize(destinations.size());
rv.ecdhInfo.resize(destinations.size());
int i = 0;
keyV masks(destinations.size()); //sk mask..
ctkeyV outSk(destinations.size());
for (i = 0; i < destinations.size(); i++) {
//add destination to sig
rv.outPk[i].dest = copy(destinations[i]);
//compute range proof
rv.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]);
#ifdef DBG
verRange(rv.outPk[i].mask, rv.rangeSigs[i]);
#endif
//mask amount and mask
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
rv.ecdhInfo[i].amount = d2h(amounts[i]);
ecdhEncode(rv.ecdhInfo[i], destinations[i]);
}
int index;
tie(rv.mixRing, index) = populateFromBlockchain(inPk, mixin);
rv.MG = proveRctMG(rv.mixRing, inSk, outSk, rv.outPk, index);
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
bool verRct(rctSig & rv) {
int i = 0;
bool rvb = true;
bool tmp;
DP("range proofs verified?");
for (i = 0; i < rv.outPk.size(); i++) {
tmp = verRange(rv.outPk[i].mask, rv.rangeSigs[i]);
DP(tmp);
rvb = (rvb && tmp);
}
bool mgVerd = verRctMG(rv.MG, rv.mixRing, rv.outPk);
DP("mg sig verified?");
DP(mgVerd);
return (rvb && mgVerd);
}
//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
xmr_amount decodeRct(rctSig & rv, key & sk, int i) {
//mask amount and mask
ecdhDecode(rv.ecdhInfo[i], sk);
key mask = rv.ecdhInfo[i].mask;
key amount = rv.ecdhInfo[i].amount;
key C = rv.outPk[i].mask;
DP("C");
DP(C);
key Ctmp;
addKeys2(Ctmp, mask, amount, H);
DP("Ctmp");
DP(Ctmp);
if (equalKeys(C, Ctmp) == false) {
printf("warning, amount decoded incorrectly, will be unable to spend");
}
return h2d(amount);
}
}

View file

@ -0,0 +1,136 @@
// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#define DBG
#ifndef RCTSIGS_H
#define RCTSIGS_H
#include <cstddef>
#include <mutex>
#include <vector>
#include <tuple>
#include "generic-ops.h"
#include "crypto-ops.h"
#include "random.h"
#include "keccak.h"
#include "crypto.h"
#include "rctTypes.h"
#include "rctOps.h"
using namespace std;
using namespace crypto;
namespace rct {
//Schnorr Non-linkable
//Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2
//Ver Verifies that signer knows an "x" such that xG = one of P1 or P2
//These are called in the below ASNL sig generation
void GenSchnorrNonLinkable(key & L1, key & s1, key & s2, const key & x, const key & P1, const key & P2, int index);
bool VerSchnorrNonLinkable(const key & P1, const key & P2, const key & L1, const key & s1, const key & s2);
//Aggregate Schnorr Non-linkable Ring Signature (ASNL)
// c.f. http://eprint.iacr.org/2015/1098 section 5.
// These are used in range proofs (alternatively Borromean could be used)
// Gen gives a signature which proves the signer knows, for each i,
// an x[i] such that x[i]G = one of P1[i] or P2[i]
// Ver Verifies the signer knows a key for one of P1[i], P2[i] at each i
asnlSig GenASNL(key64 x, key64 P1, key64 P2, bits indices);
bool VerASNL(key64 P1, key64 P2, asnlSig &as);
//Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
//These are aka MG signatutes in earlier drafts of the ring ct paper
// c.f. http://eprint.iacr.org/2015/1098 section 2.
// keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
keyV keyImageV(const keyV &xx);
mgSig MLSAG_Gen(const keyM &pk, const keyV &xx, const int index);
bool MLSAG_Ver(keyM &pk, mgSig &sig);
//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^64]
// 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
rangeSig proveRange(key & C, key & mask, const xmr_amount & amount);
bool verRange(key & C, rangeSig & as);
//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
mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const keyV &outMasks, const ctkeyV & outPk, int index);
bool verRctMG(mgSig mg, ctkeyM & pubs, ctkeyV & outPk);
//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).
void getKeyFromBlockchain(ctkey & a, size_t reference_index);
tuple<ctkeyM, xmr_amount> populateFromBlockchain(ctkeyV inPk, int mixin);
//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
rctSig genRct(ctkeyV & inSk, ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> amounts, const int mixin);
bool verRct(rctSig & rv);
xmr_amount decodeRct(rctSig & rv, key & sk, int i);
}
#endif /* RCTSIGS_H */

View file

@ -0,0 +1,209 @@
// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "rctTypes.h"
using namespace crypto;
using namespace std;
namespace rct {
//dp
//Debug printing for the above types
//Actually use DP(value) and #define DBG
void dp(key a) {
int j = 0;
printf("\"");
for (j = 0; j < 32; j++) {
printf("%02x", (unsigned char)a.bytes[j]);
}
printf("\"");
printf("\n");
}
void dp(bool a) {
printf(" ... %s ... ", a ? "true" : "false");
printf("\n");
}
void dp(char * a, int l) {
int j = 0;
printf("\"");
for (j = 0; j < l; j++) {
printf("%02x", (unsigned char)a[j]);
}
printf("\"");
printf("\n");
}
void dp(keyV a) {
int j = 0;
printf("[");
for (j = 0; j < a.size(); j++) {
dp(a[j]);
if (j < a.size() - 1) {
printf(",");
}
}
printf("]");
printf("\n");
}
void dp(keyM a) {
int j = 0;
printf("[");
for (j = 0; j < a.size(); j++) {
dp(a[j]);
if (j < a.size() - 1) {
printf(",");
}
}
printf("]");
printf("\n");
}
void dp(xmr_amount vali) {
printf("x: %"PRIu64"\n", vali);
printf("\n");
}
void dp(int vali) {
printf("x: %d\n", vali);
printf("\n");
}
void dp(bits amountb) {
int i = 0;
for (int i = 0; i < 64; i++) {
printf("%d", amountb[i]);
}
printf("\n");
}
void dp(char * st) {
printf("%s\n", st);
}
//Various Conversions
//uint long long to 32 byte key
void d2h(key & amounth, const xmr_amount in) {
sc_0(amounth.bytes);
xmr_amount val = in;
int i = 0, byte = 0;
while (val != 0) {
amounth[i] = (unsigned char)(val & 0xFF);
i++;
val /= (xmr_amount)256;
}
}
//uint long long to 32 byte key
key d2h(const xmr_amount in) {
key amounth;
sc_0(amounth.bytes);
xmr_amount val = in;
int i = 0;
while (val != 0) {
amounth[i] = (unsigned char)(val & 0xFF);
i++;
val /= (xmr_amount)256;
}
return amounth;
}
//uint long long to int[64]
void d2b(bits amountb, xmr_amount val) {
amountb;
int i = 0;
while (val != 0) {
amountb[i] = val & 1;
i++;
val >>= 1;
}
while (i < 64) {
amountb[i] = 0;
i++;
}
}
//32 byte key to uint long long
// if the key holds a value > 2^64
// then the value in the first 8 bytes is returned
xmr_amount h2d(const key & test) {
xmr_amount vali = 0;
int j = 0;
for (j = 7; j >= 0; j--) {
vali = (xmr_amount)(vali * 256 + (unsigned char)test[j]);
}
return vali;
}
//32 byte key to int[64]
void h2b(bits amountb2, const key & test) {
int val = 0, i = 0, j = 0;
for (j = 0; j < 8; j++) {
val = (unsigned char)test[j];
i = 8 * j;
while (val != 0) {
amountb2[i] = val & 1;
i++;
val >>= 1;
}
while (i < 8 * (j + 1)) {
amountb2[i] = 0;
}
}
}
//int[64] to 32 byte key
void b2h(key & amountdh, const bits amountb2) {
int byte, i, j;
for (j = 0; j < 8; j++) {
byte = 0;
//val = (unsigned char) test[j];
i = 8 * j;
for (i = 7; i > -1; i--) {
byte = byte * 2 + amountb2[8 * j + i];
}
amountdh[j] = (unsigned char)byte;
}
for (j = 8; j < 32; j++) {
amountdh[j] = (unsigned char)(0x00);
}
}
//int[64] to uint long long
xmr_amount b2d(bits amountb) {
xmr_amount vali = 0;
int j = 0;
for (j = 63; j >= 0; j--) {
vali = (xmr_amount)(vali * 2 + amountb[j]);
}
}
}

View file

@ -0,0 +1,259 @@
// Copyright (c) 2016, Monero Research Labs
//
// Author: Shen Noether <shen.noether@gmx.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#ifndef RCT_TYPES_H
#define RCT_TYPES_H
#include <cstddef>
#include <mutex>
#include <vector>
#include <tuple>
#include "generic-ops.h"
#include "crypto-ops.h"
#include "random.h"
#include "keccak.h"
#include "crypto.h"
//Define this flag when debugging to get additional info on the console
#ifdef DBG
#define DP(x) dp(x)
#else
#define DP(x)
#endif
//atomic units of moneros
#define ATOMS 64
//for printing large ints
#undef PRIu64
#define PRIu64 "I64u"
using namespace std;
using namespace crypto;
//Namespace specifically for ring ct code
namespace rct {
//basic ops containers
typedef unsigned char * Bytes;
// Can contain a secret or public key
// similar to secret_key / public_key of crypto-ops,
// but uses unsigned chars,
// also includes an operator for accessing the i'th byte.
typedef struct key {
unsigned char & operator[](int i) {
return bytes[i];
}
unsigned char bytes[32];
};
typedef vector<key> keyV; //vector of keys
typedef vector<keyV> keyM; //matrix of keys (indexed by column first)
//containers For CT operations
//if it's representing a private ctkey then "dest" contains the secret key of the address
// while "mask" contains a where C = aG + bH is CT pedersen commitment and b is the amount
// (store b, the amount, separately
//if it's representing a public ctkey, then "dest" = P the address, mask = C the commitment
struct ctkey {
key dest;
key mask; //C here if public
};
typedef vector<ctkey> ctkeyV;
typedef vector<ctkeyV> ctkeyM;
//data for passing the amount to the receiver secretly
// If the pedersen commitment to an amount is C = aG + bH,
// "mask" contains a 32 byte key a
// "amount" contains a hex representation (in 32 bytes) of a 64 bit number
// "senderPk" is not the senders actual public key, but a one-time public key generated for
// the purpose of the ECDH exchange
struct ecdhTuple {
key mask;
key amount;
key senderPk;
};
//containers for representing amounts
typedef uint64_t xmr_amount;
typedef unsigned int bits[ATOMS];
typedef key key64[64];
//just contains the necessary keys to represent asnlSigs
//c.f. http://eprint.iacr.org/2015/1098
struct asnlSig {
key64 L1;
key64 s2;
key s;
};
//just contains the necessary keys to represent MLSAG sigs
//c.f. http://eprint.iacr.org/2015/1098
struct mgSig {
keyM ss;
key cc;
keyV II;
};
//contains the data for an asnl sig
// also contains the "Ci" values such that
// \sum Ci = C
// and the signature proves that each Ci is either
// a Pedersen commitment to 0 or to 2^i
//thus proving that C is in the range of [0, 2^64]
struct rangeSig {
asnlSig asig;
key64 Ci;
};
//A container to hold all signatures necessary for RingCT
// rangeSigs holds all the rangeproof data of a transaction
// MG holds the MLSAG signature of a transaction
// mixRing holds all the public keypairs (P, C) for a transaction
// ecdhInfo holds an encoded mask / amount to be passed to each receiver
// outPk contains public keypairs which are destinations (P, C),
// P = address, C = commitment to amount
struct rctSig {
vector<rangeSig> rangeSigs;
mgSig MG;
ctkeyM mixRing; //the set of all pubkeys / copy
//pairs that you mix with
vector<ecdhTuple> ecdhInfo;
ctkeyV outPk;
};
struct rmsSig {
vector<rangeSig> rangeSigs;
mgSig MG;
ctkeyM mixRing;
vector<ecdhTuple> destinationEcdhInfo;
vector<ecdhTuple> participantEcdhInfo;
ctkeyV outPk;
};
//other basepoint H = toPoint(cn_fast_hash(G)), G the basepoint
static const key H = { {0x8b, 0x65, 0x59, 0x70, 0x15, 0x37, 0x99, 0xaf, 0x2a, 0xea, 0xdc, 0x9f, 0xf1, 0xad, 0xd0, 0xea, 0x6c, 0x72, 0x51, 0xd5, 0x41, 0x54, 0xcf, 0xa9, 0x2c, 0x17, 0x3a, 0x0d, 0xd3, 0x9c, 0x1f, 0x94} };
//H2 contains 2^i H in each index, i.e. H, 2H, 4H, 8H, ...
//This is used for the range proofG
static const key64 H2 = { {0x8b, 0x65, 0x59, 0x70, 0x15, 0x37, 0x99, 0xaf, 0x2a, 0xea, 0xdc, 0x9f, 0xf1, 0xad, 0xd0, 0xea, 0x6c, 0x72, 0x51, 0xd5, 0x41, 0x54, 0xcf, 0xa9, 0x2c, 0x17, 0x3a, 0x0d, 0xd3, 0x9c, 0x1f, 0x94},
{0x8f, 0xaa, 0x44, 0x8a, 0xe4, 0xb3, 0xe2, 0xbb, 0x3d, 0x4d, 0x13, 0x09, 0x09, 0xf5, 0x5f, 0xcd, 0x79, 0x71, 0x1c, 0x1c, 0x83, 0xcd, 0xbc, 0xca, 0xdd, 0x42, 0xcb, 0xe1, 0x51, 0x5e, 0x87, 0x12},
{0x12, 0xa7, 0xd6, 0x2c, 0x77, 0x91, 0x65, 0x4a, 0x57, 0xf3, 0xe6, 0x76, 0x94, 0xed, 0x50, 0xb4, 0x9a, 0x7d, 0x9e, 0x3f, 0xc1, 0xe4, 0xc7, 0xa0, 0xbd, 0xe2, 0x9d, 0x18, 0x7e, 0x9c, 0xc7, 0x1d},
{0x78, 0x9a, 0xb9, 0x93, 0x4b, 0x49, 0xc4, 0xf9, 0xe6, 0x78, 0x5c, 0x6d, 0x57, 0xa4, 0x98, 0xb3, 0xea, 0xd4, 0x43, 0xf0, 0x4f, 0x13, 0xdf, 0x11, 0x0c, 0x54, 0x27, 0xb4, 0xf2, 0x14, 0xc7, 0x39},
{0x77, 0x1e, 0x92, 0x99, 0xd9, 0x4f, 0x02, 0xac, 0x72, 0xe3, 0x8e, 0x44, 0xde, 0x56, 0x8a, 0xc1, 0xdc, 0xb2, 0xed, 0xc6, 0xed, 0xb6, 0x1f, 0x83, 0xca, 0x41, 0x8e, 0x10, 0x77, 0xce, 0x3d, 0xe8},
{0x73, 0xb9, 0x6d, 0xb4, 0x30, 0x39, 0x81, 0x9b, 0xda, 0xf5, 0x68, 0x0e, 0x5c, 0x32, 0xd7, 0x41, 0x48, 0x88, 0x84, 0xd1, 0x8d, 0x93, 0x86, 0x6d, 0x40, 0x74, 0xa8, 0x49, 0x18, 0x2a, 0x8a, 0x64},
{0x8d, 0x45, 0x8e, 0x1c, 0x2f, 0x68, 0xeb, 0xeb, 0xcc, 0xd2, 0xfd, 0x5d, 0x37, 0x9f, 0x5e, 0x58, 0xf8, 0x13, 0x4d, 0xf3, 0xe0, 0xe8, 0x8c, 0xad, 0x3d, 0x46, 0x70, 0x10, 0x63, 0xa8, 0xd4, 0x12},
{0x09, 0x55, 0x1e, 0xdb, 0xe4, 0x94, 0x41, 0x8e, 0x81, 0x28, 0x44, 0x55, 0xd6, 0x4b, 0x35, 0xee, 0x8a, 0xc0, 0x93, 0x06, 0x8a, 0x5f, 0x16, 0x1f, 0xa6, 0x63, 0x75, 0x59, 0x17, 0x7e, 0xf4, 0x04},
{0xd0, 0x5a, 0x88, 0x66, 0xf4, 0xdf, 0x8c, 0xee, 0x1e, 0x26, 0x8b, 0x1d, 0x23, 0xa4, 0xc5, 0x8c, 0x92, 0xe7, 0x60, 0x30, 0x97, 0x86, 0xcd, 0xac, 0x0f, 0xed, 0xa1, 0xd2, 0x47, 0xa9, 0xc9, 0xa7},
{0x55, 0xcd, 0xaa, 0xd5, 0x18, 0xbd, 0x87, 0x1d, 0xd1, 0xeb, 0x7b, 0xc7, 0x02, 0x3e, 0x1d, 0xc0, 0xfd, 0xf3, 0x33, 0x98, 0x64, 0xf8, 0x8f, 0xdd, 0x2d, 0xe2, 0x69, 0xfe, 0x9e, 0xe1, 0x83, 0x2d},
{0xe7, 0x69, 0x7e, 0x95, 0x1a, 0x98, 0xcf, 0xd5, 0x71, 0x2b, 0x84, 0xbb, 0xe5, 0xf3, 0x4e, 0xd7, 0x33, 0xe9, 0x47, 0x3f, 0xcb, 0x68, 0xed, 0xa6, 0x6e, 0x37, 0x88, 0xdf, 0x19, 0x58, 0xc3, 0x06},
{0xf9, 0x2a, 0x97, 0x0b, 0xae, 0x72, 0x78, 0x29, 0x89, 0xbf, 0xc8, 0x3a, 0xdf, 0xaa, 0x92, 0xa4, 0xf4, 0x9c, 0x7e, 0x95, 0x91, 0x8b, 0x3b, 0xba, 0x3c, 0xdc, 0x7f, 0xe8, 0x8a, 0xcc, 0x8d, 0x47},
{0x1f, 0x66, 0xc2, 0xd4, 0x91, 0xd7, 0x5a, 0xf9, 0x15, 0xc8, 0xdb, 0x6a, 0x6d, 0x1c, 0xb0, 0xcd, 0x4f, 0x7d, 0xdc, 0xd5, 0xe6, 0x3d, 0x3b, 0xa9, 0xb8, 0x3c, 0x86, 0x6c, 0x39, 0xef, 0x3a, 0x2b},
{0x3e, 0xec, 0x98, 0x84, 0xb4, 0x3f, 0x58, 0xe9, 0x3e, 0xf8, 0xde, 0xea, 0x26, 0x00, 0x04, 0xef, 0xea, 0x2a, 0x46, 0x34, 0x4f, 0xc5, 0x96, 0x5b, 0x1a, 0x7d, 0xd5, 0xd1, 0x89, 0x97, 0xef, 0xa7},
{0xb2, 0x9f, 0x8f, 0x0c, 0xcb, 0x96, 0x97, 0x7f, 0xe7, 0x77, 0xd4, 0x89, 0xd6, 0xbe, 0x9e, 0x7e, 0xbc, 0x19, 0xc4, 0x09, 0xb5, 0x10, 0x35, 0x68, 0xf2, 0x77, 0x61, 0x1d, 0x7e, 0xa8, 0x48, 0x94},
{0x56, 0xb1, 0xf5, 0x12, 0x65, 0xb9, 0x55, 0x98, 0x76, 0xd5, 0x8d, 0x24, 0x9d, 0x0c, 0x14, 0x6d, 0x69, 0xa1, 0x03, 0x63, 0x66, 0x99, 0x87, 0x4d, 0x3f, 0x90, 0x47, 0x35, 0x50, 0xfe, 0x3f, 0x2c},
{0x1d, 0x7a, 0x36, 0x57, 0x5e, 0x22, 0xf5, 0xd1, 0x39, 0xff, 0x9c, 0xc5, 0x10, 0xfa, 0x13, 0x85, 0x05, 0x57, 0x6b, 0x63, 0x81, 0x5a, 0x94, 0xe4, 0xb0, 0x12, 0xbf, 0xd4, 0x57, 0xca, 0xaa, 0xda},
{0xd0, 0xac, 0x50, 0x7a, 0x86, 0x4e, 0xcd, 0x05, 0x93, 0xfa, 0x67, 0xbe, 0x7d, 0x23, 0x13, 0x43, 0x92, 0xd0, 0x0e, 0x40, 0x07, 0xe2, 0x53, 0x48, 0x78, 0xd9, 0xb2, 0x42, 0xe1, 0x0d, 0x76, 0x20},
{0xf6, 0xc6, 0x84, 0x0b, 0x9c, 0xf1, 0x45, 0xbb, 0x2d, 0xcc, 0xf8, 0x6e, 0x94, 0x0b, 0xe0, 0xfc, 0x09, 0x8e, 0x32, 0xe3, 0x10, 0x99, 0xd5, 0x6f, 0x7f, 0xe0, 0x87, 0xbd, 0x5d, 0xeb, 0x50, 0x94},
{0x28, 0x83, 0x1a, 0x33, 0x40, 0x07, 0x0e, 0xb1, 0xdb, 0x87, 0xc1, 0x2e, 0x05, 0x98, 0x0d, 0x5f, 0x33, 0xe9, 0xef, 0x90, 0xf8, 0x3a, 0x48, 0x17, 0xc9, 0xf4, 0xa0, 0xa3, 0x32, 0x27, 0xe1, 0x97},
{0x87, 0x63, 0x22, 0x73, 0xd6, 0x29, 0xcc, 0xb7, 0xe1, 0xed, 0x1a, 0x76, 0x8f, 0xa2, 0xeb, 0xd5, 0x17, 0x60, 0xf3, 0x2e, 0x1c, 0x0b, 0x86, 0x7a, 0x5d, 0x36, 0x8d, 0x52, 0x71, 0x05, 0x5c, 0x6e},
{0x5c, 0x7b, 0x29, 0x42, 0x43, 0x47, 0x96, 0x4d, 0x04, 0x27, 0x55, 0x17, 0xc5, 0xae, 0x14, 0xb6, 0xb5, 0xea, 0x27, 0x98, 0xb5, 0x73, 0xfc, 0x94, 0xe6, 0xe4, 0x4a, 0x53, 0x21, 0x60, 0x0c, 0xfb},
{0xe6, 0x94, 0x50, 0x42, 0xd7, 0x8b, 0xc2, 0xc3, 0xbd, 0x6e, 0xc5, 0x8c, 0x51, 0x1a, 0x9f, 0xe8, 0x59, 0xc0, 0xad, 0x63, 0xfd, 0xe4, 0x94, 0xf5, 0x03, 0x9e, 0x0e, 0x82, 0x32, 0x61, 0x2b, 0xd5},
{0x36, 0xd5, 0x69, 0x07, 0xe2, 0xec, 0x74, 0x5d, 0xb6, 0xe5, 0x4f, 0x0b, 0x2e, 0x1b, 0x23, 0x00, 0xab, 0xcb, 0x42, 0x2e, 0x71, 0x2d, 0xa5, 0x88, 0xa4, 0x0d, 0x3f, 0x1e, 0xbb, 0xbe, 0x02, 0xf6},
{0x34, 0xdb, 0x6e, 0xe4, 0xd0, 0x60, 0x8e, 0x5f, 0x78, 0x36, 0x50, 0x49, 0x5a, 0x3b, 0x2f, 0x52, 0x73, 0xc5, 0x13, 0x4e, 0x52, 0x84, 0xe4, 0xfd, 0xf9, 0x66, 0x27, 0xbb, 0x16, 0xe3, 0x1e, 0x6b},
{0x8e, 0x76, 0x59, 0xfb, 0x45, 0xa3, 0x78, 0x7d, 0x67, 0x4a, 0xe8, 0x67, 0x31, 0xfa, 0xa2, 0x53, 0x8e, 0xc0, 0xfd, 0xf4, 0x42, 0xab, 0x26, 0xe9, 0xc7, 0x91, 0xfa, 0xda, 0x08, 0x94, 0x67, 0xe9},
{0x30, 0x06, 0xcf, 0x19, 0x8b, 0x24, 0xf3, 0x1b, 0xb4, 0xc7, 0xe6, 0x34, 0x60, 0x00, 0xab, 0xc7, 0x01, 0xe8, 0x27, 0xcf, 0xbb, 0x5d, 0xf5, 0x2d, 0xcf, 0xa4, 0x2e, 0x9c, 0xa9, 0xff, 0x08, 0x02},
{0xf5, 0xfd, 0x40, 0x3c, 0xb6, 0xe8, 0xbe, 0x21, 0x47, 0x2e, 0x37, 0x7f, 0xfd, 0x80, 0x5a, 0x8c, 0x60, 0x83, 0xea, 0x48, 0x03, 0xb8, 0x48, 0x53, 0x89, 0xcc, 0x3e, 0xbc, 0x21, 0x5f, 0x00, 0x2a},
{0x37, 0x31, 0xb2, 0x60, 0xeb, 0x3f, 0x94, 0x82, 0xe4, 0x5f, 0x1c, 0x3f, 0x3b, 0x9d, 0xcf, 0x83, 0x4b, 0x75, 0xe6, 0xee, 0xf8, 0xc4, 0x0f, 0x46, 0x1e, 0xa2, 0x7e, 0x8b, 0x6e, 0xd9, 0x47, 0x3d},
{0x9f, 0x9d, 0xab, 0x09, 0xc3, 0xf5, 0xe4, 0x28, 0x55, 0xc2, 0xde, 0x97, 0x1b, 0x65, 0x93, 0x28, 0xa2, 0xdb, 0xc4, 0x54, 0x84, 0x5f, 0x39, 0x6f, 0xfc, 0x05, 0x3f, 0x0b, 0xb1, 0x92, 0xf8, 0xc3},
{0x5e, 0x05, 0x5d, 0x25, 0xf8, 0x5f, 0xdb, 0x98, 0xf2, 0x73, 0xe4, 0xaf, 0xe0, 0x84, 0x64, 0xc0, 0x03, 0xb7, 0x0f, 0x1e, 0xf0, 0x67, 0x7b, 0xb5, 0xe2, 0x57, 0x06, 0x40, 0x0b, 0xe6, 0x20, 0xa5},
{0x86, 0x8b, 0xcf, 0x36, 0x79, 0xcb, 0x6b, 0x50, 0x0b, 0x94, 0x41, 0x8c, 0x0b, 0x89, 0x25, 0xf9, 0x86, 0x55, 0x30, 0x30, 0x3a, 0xe4, 0xe4, 0xb2, 0x62, 0x59, 0x18, 0x65, 0x66, 0x6a, 0x45, 0x90},
{0xb3, 0xdb, 0x6b, 0xd3, 0x89, 0x7a, 0xfb, 0xd1, 0xdf, 0x3f, 0x96, 0x44, 0xab, 0x21, 0xc8, 0x05, 0x0e, 0x1f, 0x00, 0x38, 0xa5, 0x2f, 0x7c, 0xa9, 0x5a, 0xc0, 0xc3, 0xde, 0x75, 0x58, 0xcb, 0x7a},
{0x81, 0x19, 0xb3, 0xa0, 0x59, 0xff, 0x2c, 0xac, 0x48, 0x3e, 0x69, 0xbc, 0xd4, 0x1d, 0x6d, 0x27, 0x14, 0x94, 0x47, 0x91, 0x42, 0x88, 0xbb, 0xea, 0xee, 0x34, 0x13, 0xe6, 0xdc, 0xc6, 0xd1, 0xeb},
{0x10, 0xfc, 0x58, 0xf3, 0x5f, 0xc7, 0xfe, 0x7a, 0xe8, 0x75, 0x52, 0x4b, 0xb5, 0x85, 0x00, 0x03, 0x00, 0x5b, 0x7f, 0x97, 0x8c, 0x0c, 0x65, 0xe2, 0xa9, 0x65, 0x46, 0x4b, 0x6d, 0x00, 0x81, 0x9c},
{0x5a, 0xcd, 0x94, 0xeb, 0x3c, 0x57, 0x83, 0x79, 0xc1, 0xea, 0x58, 0xa3, 0x43, 0xec, 0x4f, 0xcf, 0xf9, 0x62, 0x77, 0x6f, 0xe3, 0x55, 0x21, 0xe4, 0x75, 0xa0, 0xe0, 0x6d, 0x88, 0x7b, 0x2d, 0xb9},
{0x33, 0xda, 0xf3, 0xa2, 0x14, 0xd6, 0xe0, 0xd4, 0x2d, 0x23, 0x00, 0xa7, 0xb4, 0x4b, 0x39, 0x29, 0x0d, 0xb8, 0x98, 0x9b, 0x42, 0x79, 0x74, 0xcd, 0x86, 0x5d, 0xb0, 0x11, 0x05, 0x5a, 0x29, 0x01},
{0xcf, 0xc6, 0x57, 0x2f, 0x29, 0xaf, 0xd1, 0x64, 0xa4, 0x94, 0xe6, 0x4e, 0x6f, 0x1a, 0xeb, 0x82, 0x0c, 0x3e, 0x7d, 0xa3, 0x55, 0x14, 0x4e, 0x51, 0x24, 0xa3, 0x91, 0xd0, 0x6e, 0x9f, 0x95, 0xea},
{0xd5, 0x31, 0x2a, 0x4b, 0x0e, 0xf6, 0x15, 0xa3, 0x31, 0xf6, 0x35, 0x2c, 0x2e, 0xd2, 0x1d, 0xac, 0x9e, 0x7c, 0x36, 0x39, 0x8b, 0x93, 0x9a, 0xec, 0x90, 0x1c, 0x25, 0x7f, 0x6c, 0xbc, 0x9e, 0x8e},
{0x55, 0x1d, 0x67, 0xfe, 0xfc, 0x7b, 0x5b, 0x9f, 0x9f, 0xdb, 0xf6, 0xaf, 0x57, 0xc9, 0x6c, 0x8a, 0x74, 0xd7, 0xe4, 0x5a, 0x00, 0x20, 0x78, 0xa7, 0xb5, 0xba, 0x45, 0xc6, 0xfd, 0xe9, 0x3e, 0x33},
{0xd5, 0x0a, 0xc7, 0xbd, 0x5c, 0xa5, 0x93, 0xc6, 0x56, 0x92, 0x8f, 0x38, 0x42, 0x80, 0x17, 0xfc, 0x7b, 0xa5, 0x02, 0x85, 0x4c, 0x43, 0xd8, 0x41, 0x49, 0x50, 0xe9, 0x6e, 0xcb, 0x40, 0x5d, 0xc3},
{0x07, 0x73, 0xe1, 0x8e, 0xa1, 0xbe, 0x44, 0xfe, 0x1a, 0x97, 0xe2, 0x39, 0x57, 0x3c, 0xfa, 0xe3, 0xe4, 0xe9, 0x5e, 0xf9, 0xaa, 0x9f, 0xaa, 0xbe, 0xac, 0x12, 0x74, 0xd3, 0xad, 0x26, 0x16, 0x04},
{0xe9, 0xaf, 0x0e, 0x7c, 0xa8, 0x93, 0x30, 0xd2, 0xb8, 0x61, 0x5d, 0x1b, 0x41, 0x37, 0xca, 0x61, 0x7e, 0x21, 0x29, 0x7f, 0x2f, 0x0d, 0xed, 0x8e, 0x31, 0xb7, 0xd2, 0xea, 0xd8, 0x71, 0x46, 0x60},
{0x7b, 0x12, 0x45, 0x83, 0x09, 0x7f, 0x10, 0x29, 0xa0, 0xc7, 0x41, 0x91, 0xfe, 0x73, 0x78, 0xc9, 0x10, 0x5a, 0xcc, 0x70, 0x66, 0x95, 0xed, 0x14, 0x93, 0xbb, 0x76, 0x03, 0x42, 0x26, 0xa5, 0x7b},
{0xec, 0x40, 0x05, 0x7b, 0x99, 0x54, 0x76, 0x65, 0x0b, 0x3d, 0xb9, 0x8e, 0x9d, 0xb7, 0x57, 0x38, 0xa8, 0xcd, 0x2f, 0x94, 0xd8, 0x63, 0xb9, 0x06, 0x15, 0x0c, 0x56, 0xaa, 0xc1, 0x9c, 0xaa, 0x6b},
{0x01, 0xd9, 0xff, 0x72, 0x9e, 0xfd, 0x39, 0xd8, 0x37, 0x84, 0xc0, 0xfe, 0x59, 0xc4, 0xae, 0x81, 0xa6, 0x70, 0x34, 0xcb, 0x53, 0xc9, 0x43, 0xfb, 0x81, 0x8b, 0x9d, 0x8a, 0xe7, 0xfc, 0x33, 0xe5},
{0x00, 0xdf, 0xb3, 0xc6, 0x96, 0x32, 0x8c, 0x76, 0x42, 0x45, 0x19, 0xa7, 0xbe, 0xfe, 0x8e, 0x0f, 0x6c, 0x76, 0xf9, 0x47, 0xb5, 0x27, 0x67, 0x91, 0x6d, 0x24, 0x82, 0x3f, 0x73, 0x5b, 0xaf, 0x2e},
{0x46, 0x1b, 0x79, 0x9b, 0x4d, 0x9c, 0xee, 0xa8, 0xd5, 0x80, 0xdc, 0xb7, 0x6d, 0x11, 0x15, 0x0d, 0x53, 0x5e, 0x16, 0x39, 0xd1, 0x60, 0x03, 0xc3, 0xfb, 0x7e, 0x9d, 0x1f, 0xd1, 0x30, 0x83, 0xa8},
{0xee, 0x03, 0x03, 0x94, 0x79, 0xe5, 0x22, 0x8f, 0xdc, 0x55, 0x1c, 0xbd, 0xe7, 0x07, 0x9d, 0x34, 0x12, 0xea, 0x18, 0x6a, 0x51, 0x7c, 0xcc, 0x63, 0xe4, 0x6e, 0x9f, 0xcc, 0xe4, 0xfe, 0x3a, 0x6c},
{0xa8, 0xcf, 0xb5, 0x43, 0x52, 0x4e, 0x7f, 0x02, 0xb9, 0xf0, 0x45, 0xac, 0xd5, 0x43, 0xc2, 0x1c, 0x37, 0x3b, 0x4c, 0x9b, 0x98, 0xac, 0x20, 0xce, 0xc4, 0x17, 0xa6, 0xdd, 0xb5, 0x74, 0x4e, 0x94},
{0x93, 0x2b, 0x79, 0x4b, 0xf8, 0x9c, 0x6e, 0xda, 0xf5, 0xd0, 0x65, 0x0c, 0x7c, 0x4b, 0xad, 0x92, 0x42, 0xb2, 0x56, 0x26, 0xe3, 0x7e, 0xad, 0x5a, 0xa7, 0x5e, 0xc8, 0xc6, 0x4e, 0x09, 0xdd, 0x4f},
{0x16, 0xb1, 0x0c, 0x77, 0x9c, 0xe5, 0xcf, 0xef, 0x59, 0xc7, 0x71, 0x0d, 0x2e, 0x68, 0x44, 0x1e, 0xa6, 0xfa, 0xcb, 0x68, 0xe9, 0xb5, 0xf7, 0xd5, 0x33, 0xae, 0x0b, 0xb7, 0x8e, 0x28, 0xbf, 0x57},
{0x0f, 0x77, 0xc7, 0x67, 0x43, 0xe7, 0x39, 0x6f, 0x99, 0x10, 0x13, 0x9f, 0x49, 0x37, 0xd8, 0x37, 0xae, 0x54, 0xe2, 0x10, 0x38, 0xac, 0x5c, 0x0b, 0x3f, 0xd6, 0xef, 0x17, 0x1a, 0x28, 0xa7, 0xe4},
{0xd7, 0xe5, 0x74, 0xb7, 0xb9, 0x52, 0xf2, 0x93, 0xe8, 0x0d, 0xde, 0x90, 0x5e, 0xb5, 0x09, 0x37, 0x3f, 0x3f, 0x6c, 0xd1, 0x09, 0xa0, 0x22, 0x08, 0xb3, 0xc1, 0xe9, 0x24, 0x08, 0x0a, 0x20, 0xca},
{0x45, 0x66, 0x6f, 0x8c, 0x38, 0x1e, 0x3d, 0xa6, 0x75, 0x56, 0x3f, 0xf8, 0xba, 0x23, 0xf8, 0x3b, 0xfa, 0xc3, 0x0c, 0x34, 0xab, 0xdd, 0xe6, 0xe5, 0xc0, 0x97, 0x5e, 0xf9, 0xfd, 0x70, 0x0c, 0xb9},
{0xb2, 0x46, 0x12, 0xe4, 0x54, 0x60, 0x7e, 0xb1, 0xab, 0xa4, 0x47, 0xf8, 0x16, 0xd1, 0xa4, 0x55, 0x1e, 0xf9, 0x5f, 0xa7, 0x24, 0x7f, 0xb7, 0xc1, 0xf5, 0x03, 0x02, 0x0a, 0x71, 0x77, 0xf0, 0xdd},
{0x7e, 0x20, 0x88, 0x61, 0x85, 0x6d, 0xa4, 0x2c, 0x8b, 0xb4, 0x6a, 0x75, 0x67, 0xf8, 0x12, 0x13, 0x62, 0xd9, 0xfb, 0x24, 0x96, 0xf1, 0x31, 0xa4, 0xaa, 0x90, 0x17, 0xcf, 0x36, 0x6c, 0xdf, 0xce},
{0x5b, 0x64, 0x6b, 0xff, 0x6a, 0xd1, 0x10, 0x01, 0x65, 0x03, 0x7a, 0x05, 0x56, 0x01, 0xea, 0x02, 0x35, 0x8c, 0x0f, 0x41, 0x05, 0x0f, 0x9d, 0xfe, 0x3c, 0x95, 0xdc, 0xcb, 0xd3, 0x08, 0x7b, 0xe0},
{0x74, 0x6d, 0x1d, 0xcc, 0xfe, 0xd2, 0xf0, 0xff, 0x1e, 0x13, 0xc5, 0x1e, 0x2d, 0x50, 0xd5, 0x32, 0x43, 0x75, 0xfb, 0xd5, 0xbf, 0x7c, 0xa8, 0x2a, 0x89, 0x31, 0x82, 0x8d, 0x80, 0x1d, 0x43, 0xab},
{0xcb, 0x98, 0x11, 0x0d, 0x4a, 0x6b, 0xb9, 0x7d, 0x22, 0xfe, 0xad, 0xbc, 0x6c, 0x0d, 0x89, 0x30, 0xc5, 0xf8, 0xfc, 0x50, 0x8b, 0x2f, 0xc5, 0xb3, 0x53, 0x28, 0xd2, 0x6b, 0x88, 0xdb, 0x19, 0xae},
{0x60, 0xb6, 0x26, 0xa0, 0x33, 0xb5, 0x5f, 0x27, 0xd7, 0x67, 0x6c, 0x40, 0x95, 0xea, 0xba, 0xbc, 0x7a, 0x2c, 0x7e, 0xde, 0x26, 0x24, 0xb4, 0x72, 0xe9, 0x7f, 0x64, 0xf9, 0x6b, 0x8c, 0xfc, 0x0e},
{0xe5, 0xb5, 0x2b, 0xc9, 0x27, 0x46, 0x8d, 0xf7, 0x18, 0x93, 0xeb, 0x81, 0x97, 0xef, 0x82, 0x0c, 0xf7, 0x6c, 0xb0, 0xaa, 0xf6, 0xe8, 0xe4, 0xfe, 0x93, 0xad, 0x62, 0xd8, 0x03, 0x98, 0x31, 0x04},
{0x05, 0x65, 0x41, 0xae, 0x5d, 0xa9, 0x96, 0x1b, 0xe2, 0xb0, 0xa5, 0xe8, 0x95, 0xe5, 0xc5, 0xba, 0x15, 0x3c, 0xbb, 0x62, 0xdd, 0x56, 0x1a, 0x42, 0x7b, 0xad, 0x0f, 0xfd, 0x41, 0x92, 0x31, 0x99} };
//Debug printing for the above types
//Actually use DP(value) and #define DBG
void dp(key a);
void dp(bool a);
void dp(char * a, int l);
void dp(keyV a);
void dp(keyM a);
void dp(xmr_amount vali);
void dp(int vali);
void dp(bits amountb);
void dp(char * st);
//various conversions
//uint long long to 32 byte key
void d2h(key & amounth, xmr_amount val);
key d2h(xmr_amount val);
//uint long long to int[64]
void d2b(bits amountb, xmr_amount val);
//32 byte key to uint long long
// if the key holds a value > 2^64
// then the value in the first 8 bytes is returned
xmr_amount h2d(const key &test);
//32 byte key to int[64]
void h2b(bits amountb2, key & test);
//int[64] to 32 byte key
void b2h(key & amountdh, bits amountb2);
//int[64] to uint long long
xmr_amount b2d(bits amountb);
}
#endif /* RCTTYPES_H */

View file

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

View file

@ -0,0 +1,5 @@
#!/bin/sh
gtags.exe
make clean
make
./a.exe

View file

@ -0,0 +1 @@
%1

View file

@ -0,0 +1,98 @@
#pragma once
#include <limits>
#include <type_traits>
#include <utility>
#include <sstream>
#include <string>
/*! \file varint.h
* \breif provides the implementation of varint's
*
* The representation of varints is rather odd. The first bit of each
* octet is significant, it represents wheter there is another part
* waiting to be read. For example 0x8002 would return 0x200, even
* though 0x02 does not have its msb set. The actual way they are read
* is as follows: Strip the msb of each byte, then from left to right,
* read in what remains, placing it in reverse, into the buffer. Thus,
* the following bit stream: 0xff02 would return 0x027f. 0xff turns
* into 0x7f, is placed on the beggining of the buffer, then 0x02 is
* unchanged, since its msb is not set, and placed at the end of the
* buffer.
*/
namespace tools {
/*! \brief Error codes for varint
*/
enum {
/* \brief Represents the overflow error */
EVARINT_OVERFLOW = -1,
/* \brief Represents a non conical represnetation */
EVARINT_REPRESENT = -2,
};
/*! \brief writes a varint to a stream.
*/
template<typename OutputIt, typename T>
/* Requires T to be both an integral type and unsigned, should be a compile error if it is not */
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, void>::type
write_varint(OutputIt &&dest, T i) {
/* Make sure that there is one after this */
while (i >= 0x80) {
*dest = (static_cast<char>(i) & 0x7f) | 0x80;
++dest;
i >>= 7; /* I should be in multiples of 7, this should just get the next part */
}
/* writes the last one to dest */
*dest = static_cast<char>(i);
dest++; /* Seems kinda pointless... */
}
/*! \brief Returns the string that represents the varint
*/
template<typename T>
std::string get_varint_data(const T& v)
{
std::stringstream ss;
write_varint(std::ostreambuf_iterator<char>(ss), v);
return ss.str();
}
/*! \brief reads in the varint that is pointed to by InputIt into write
*/
template<int bits, typename InputIt, typename T>
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value && 0 <= bits && bits <= std::numeric_limits<T>::digits, int>::type
read_varint(InputIt &&first, InputIt &&last, T &write) {
int read = 0;
write = 0;
for (int shift = 0;; shift += 7) {
if (first == last) {
return read;
}
unsigned char byte = *first;
++first;
++read;
if (shift + 7 >= bits && byte >= 1 << (bits - shift)) {
return EVARINT_OVERFLOW;
}
if (byte == 0 && shift != 0) {
return EVARINT_REPRESENT;
}
write |= static_cast<T>(byte & 0x7f) << shift; /* Does the actualy placing into write, stripping the first bit */
/* If there is no next */
if ((byte & 0x80) == 0) {
break;
}
}
return read;
}
/*! \brief Wrapper around the other read_varint,
* Sets template parameters for you.
*/
template<typename InputIt, typename T>
int read_varint(InputIt &&first, InputIt &&last, T &i) {
return read_varint<std::numeric_limits<T>::digits, InputIt, T>(std::move(first), std::move(last), i);
}
}

View file

@ -0,0 +1,11 @@
#pragma once
#if defined(__clang__)
#define DISABLE_GCC_WARNING(w)
#define DISABLE_CLANG_WARNING DISABLE_GCC_AND_CLANG_WARNING
#else
#define DISABLE_GCC_WARNING DISABLE_GCC_AND_CLANG_WARNING
#define DISABLE_CLANG_WARNING(w)
#endif
#define DISABLE_GCC_AND_CLANG_WARNING(w)