mirror of
https://github.com/monero-project/research-lab.git
synced 2024-11-17 08:17:38 +00:00
Merge pull request #1 from ShenNoether/master
Added MRL0005 formatted, RingCT code and updated MiniNero code
This commit is contained in:
commit
8ab5e066dd
96 changed files with 33954 additions and 1 deletions
File diff suppressed because it is too large
Load diff
|
@ -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}
|
||||
}
|
||||
|
|
@ -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}}
|
||||
|
|
Binary file not shown.
113
source-code/MiniNero/ASNL.py
Normal file
113
source-code/MiniNero/ASNL.py
Normal 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
|
||||
|
5
source-code/MiniNero/AggregateSchnorrCT.hash
Normal file
5
source-code/MiniNero/AggregateSchnorrCT.hash
Normal file
|
@ -0,0 +1,5 @@
|
|||
9
|
||||
0
|
||||
('checksum', '7$Z:')
|
||||
1B2yLX66Q3K49NJnNF9h6Yv4aB4oUxbPC5
|
||||
https://blockchain.info/address/1B2yLX66Q3K49NJnNF9h6Yv4aB4oUxbPC5
|
BIN
source-code/MiniNero/AggregateSchnorrCT_copy.pdf
Normal file
BIN
source-code/MiniNero/AggregateSchnorrCT_copy.pdf
Normal file
Binary file not shown.
6
source-code/MiniNero/Dec23Overleaf.hash
Normal file
6
source-code/MiniNero/Dec23Overleaf.hash
Normal 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
|
52
source-code/MiniNero/Deterministic.py
Normal file
52
source-code/MiniNero/Deterministic.py
Normal 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()
|
||||
|
17
source-code/MiniNero/Ecdh.py
Normal file
17
source-code/MiniNero/Ecdh.py
Normal 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
|
||||
|
2
source-code/MiniNero/FS_Signatures.py
Normal file
2
source-code/MiniNero/FS_Signatures.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
import MiniNero
|
||||
import PaperWallet
|
9
source-code/MiniNero/GenLookup.py
Normal file
9
source-code/MiniNero/GenLookup.py
Normal 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))
|
||||
|
348
source-code/MiniNero/Keccak.py
Normal file
348
source-code/MiniNero/Keccak.py
Normal 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]
|
96
source-code/MiniNero/Keccak.txt
Normal file
96
source-code/MiniNero/Keccak.txt
Normal 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]]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
110
source-code/MiniNero/Knapsack.py
Normal file
110
source-code/MiniNero/Knapsack.py
Normal 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)
|
55
source-code/MiniNero/LLW_Sigs.py
Normal file
55
source-code/MiniNero/LLW_Sigs.py
Normal 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
|
16384
source-code/MiniNero/LookupValues.txt
Normal file
16384
source-code/MiniNero/LookupValues.txt
Normal file
File diff suppressed because it is too large
Load diff
85
source-code/MiniNero/MLSAG.py
Normal file
85
source-code/MiniNero/MLSAG.py
Normal 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
|
100
source-code/MiniNero/MLSAG2.py
Normal file
100
source-code/MiniNero/MLSAG2.py
Normal 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])
|
||||
|
261
source-code/MiniNero/MiniNero.py
Normal file
261
source-code/MiniNero/MiniNero.py
Normal 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)
|
1
source-code/MiniNero/MiniNeroPubKey.py
Normal file
1
source-code/MiniNero/MiniNeroPubKey.py
Normal file
|
@ -0,0 +1 @@
|
|||
MiniNeroPk = 'cd9db8fafbf2b99605cee870ada0dd64ae5a583a4414c3d5d34e8e8072d520b6'
|
50
source-code/MiniNero/MoneroProof.py
Normal file
50
source-code/MiniNero/MoneroProof.py
Normal 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")
|
||||
|
19
source-code/MiniNero/MyMoneroImport.py
Normal file
19
source-code/MiniNero/MyMoneroImport.py
Normal 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))
|
97
source-code/MiniNero/Old_Ring_CT.py
Normal file
97
source-code/MiniNero/Old_Ring_CT.py
Normal 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)
|
60
source-code/MiniNero/PaperWallet.py
Normal file
60
source-code/MiniNero/PaperWallet.py
Normal 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()
|
143
source-code/MiniNero/RCTUnitTests.py
Normal file
143
source-code/MiniNero/RCTUnitTests.py
Normal 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))
|
123
source-code/MiniNero/RingCT.py
Normal file
123
source-code/MiniNero/RingCT.py
Normal 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
|
||||
|
BIN
source-code/MiniNero/RingCT0.1.hash
Normal file
BIN
source-code/MiniNero/RingCT0.1.hash
Normal file
Binary file not shown.
BIN
source-code/MiniNero/RingCT0.1_copy.pdf
Normal file
BIN
source-code/MiniNero/RingCT0.1_copy.pdf
Normal file
Binary file not shown.
5
source-code/MiniNero/RingCT0.2.hash
Normal file
5
source-code/MiniNero/RingCT0.2.hash
Normal file
|
@ -0,0 +1,5 @@
|
|||
724
|
||||
0
|
||||
('checksum', '`\xb1w\xce')
|
||||
1FpHkeBrkjffXd37y7bwa7gBJDUnvSrkS1
|
||||
https://blockchain.info/address/1FpHkeBrkjffXd37y7bwa7gBJDUnvSrkS1
|
BIN
source-code/MiniNero/RingCT0.2_copy.pdf
Normal file
BIN
source-code/MiniNero/RingCT0.2_copy.pdf
Normal file
Binary file not shown.
6
source-code/MiniNero/RingCT0.3.hash
Normal file
6
source-code/MiniNero/RingCT0.3.hash
Normal file
|
@ -0,0 +1,6 @@
|
|||
943
|
||||
0
|
||||
('checksum', 'E\xc1Lg')
|
||||
1N8g2cVBnZvq7GrfvTrmWTqXwPQZhAghf4
|
||||
https://blockchain.info/address/1N8g2cVBnZvq7GrfvTrmWTqXwPQZhAghf4
|
||||
Created new window in existing browser session.
|
BIN
source-code/MiniNero/RingCT0.3.pdf
Normal file
BIN
source-code/MiniNero/RingCT0.3.pdf
Normal file
Binary file not shown.
5
source-code/MiniNero/RingCT0.4.hash
Normal file
5
source-code/MiniNero/RingCT0.4.hash
Normal file
|
@ -0,0 +1,5 @@
|
|||
811
|
||||
0
|
||||
('checksum', '\x9e\xb9\xce\xc4')
|
||||
12ioqmWrLT5rjH3eDcgra2Bog6AfXDd83u
|
||||
https://blockchain.info/address/12ioqmWrLT5rjH3eDcgra2Bog6AfXDd83u
|
BIN
source-code/MiniNero/RingCT0.4_copy.pdf
Normal file
BIN
source-code/MiniNero/RingCT0.4_copy.pdf
Normal file
Binary file not shown.
BIN
source-code/MiniNero/RingCT0.5_copy.pdf
Normal file
BIN
source-code/MiniNero/RingCT0.5_copy.pdf
Normal file
Binary file not shown.
331
source-code/MiniNero/RingCT2.py
Normal file
331
source-code/MiniNero/RingCT2.py
Normal 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)
|
||||
|
23
source-code/MiniNero/RingCTExampleOutput.txt
Normal file
23
source-code/MiniNero/RingCTExampleOutput.txt
Normal 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')
|
8
source-code/MiniNero/RingMultisigv1.py
Normal file
8
source-code/MiniNero/RingMultisigv1.py
Normal 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,
|
17
source-code/MiniNero/SimpleBitmonerodTest.py
Normal file
17
source-code/MiniNero/SimpleBitmonerodTest.py
Normal 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)
|
||||
|
35
source-code/MiniNero/SimpleGetTime.py
Normal file
35
source-code/MiniNero/SimpleGetTime.py
Normal 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))
|
57
source-code/MiniNero/SimpleRequester.py
Normal file
57
source-code/MiniNero/SimpleRequester.py
Normal 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
|
88
source-code/MiniNero/SimpleServer.py
Normal file
88
source-code/MiniNero/SimpleServer.py
Normal 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()
|
16
source-code/MiniNero/SimpleSign.py
Normal file
16
source-code/MiniNero/SimpleSign.py
Normal 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))
|
||||
|
3
source-code/MiniNero/SimpleWallet.py
Normal file
3
source-code/MiniNero/SimpleWallet.py
Normal 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")
|
48
source-code/MiniNero/SimpleXMR2.py
Normal file
48
source-code/MiniNero/SimpleXMR2.py
Normal 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)
|
||||
|
22
source-code/MiniNero/TacoTimeExample.py
Normal file
22
source-code/MiniNero/TacoTimeExample.py
Normal 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)
|
||||
|
19
source-code/MiniNero/TactoTimeKeyChains.py
Normal file
19
source-code/MiniNero/TactoTimeKeyChains.py
Normal 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)
|
377
source-code/MiniNero/Test.py
Normal file
377
source-code/MiniNero/Test.py
Normal 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)))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
54
source-code/MiniNero/Translator.py
Normal file
54
source-code/MiniNero/Translator.py
Normal 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("}")
|
||||
|
||||
|
179
source-code/MiniNero/bitmonerod.py
Normal file
179
source-code/MiniNero/bitmonerod.py
Normal 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
|
17
source-code/MiniNero/brief/MakeClass.lua
Normal file
17
source-code/MiniNero/brief/MakeClass.lua
Normal 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
|
4
source-code/MiniNero/brief/runtest.bat
Normal file
4
source-code/MiniNero/brief/runtest.bat
Normal file
|
@ -0,0 +1,4 @@
|
|||
gtags.exe
|
||||
mingw32-make.exe clean
|
||||
mingw32-make.exe
|
||||
a.exe > .results
|
4
source-code/MiniNero/brief/runtest.sh
Normal file
4
source-code/MiniNero/brief/runtest.sh
Normal file
|
@ -0,0 +1,4 @@
|
|||
gtags.exe
|
||||
make clean
|
||||
make
|
||||
./a.exe
|
3
source-code/MiniNero/brief/runtest2.sh
Normal file
3
source-code/MiniNero/brief/runtest2.sh
Normal file
|
@ -0,0 +1,3 @@
|
|||
rm.exe a.exe
|
||||
g++ bits.cpp
|
||||
./a.exe
|
1
source-code/MiniNero/brief/tasks.bat
Normal file
1
source-code/MiniNero/brief/tasks.bat
Normal file
|
@ -0,0 +1 @@
|
|||
%1
|
132
source-code/MiniNero/btcProof.py
Normal file
132
source-code/MiniNero/btcProof.py
Normal 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)
|
129
source-code/MiniNero/ed25519.py
Normal file
129
source-code/MiniNero/ed25519.py
Normal 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
|
1704
source-code/MiniNero/mnemonic.py
Normal file
1704
source-code/MiniNero/mnemonic.py
Normal file
File diff suppressed because it is too large
Load diff
6
source-code/MiniNero/mrl_notes0.4.hash
Normal file
6
source-code/MiniNero/mrl_notes0.4.hash
Normal file
|
@ -0,0 +1,6 @@
|
|||
> python btcProof.py mrl_notes0.4_copy.pdf
|
||||
779
|
||||
0
|
||||
('checksum', '\xd3DC~')
|
||||
15jVTLpbuU6cH39aqDxWWSb1UnKS2J7MbT
|
||||
https://blockchain.info/address/15jVTLpbuU6cH39aqDxWWSb1UnKS2J7MbT
|
BIN
source-code/MiniNero/mrl_notes0.4_copy.pdf
Normal file
BIN
source-code/MiniNero/mrl_notes0.4_copy.pdf
Normal file
Binary file not shown.
8
source-code/MiniNero/mrl_notes_v0.3.hash
Normal file
8
source-code/MiniNero/mrl_notes_v0.3.hash
Normal file
|
@ -0,0 +1,8 @@
|
|||
15
|
||||
0
|
||||
('checksum', '\xe2\xee\x11O')
|
||||
bitcoin:12axbjZYAasGTnC9ADsaQfmAjEBYpWf82z?amount=0.0001
|
||||
15
|
||||
0
|
||||
('checksum', '\xe2\xee\x11O')
|
||||
12axbjZYAasGTnC9ADsaQfmAjEBYpWf82z
|
BIN
source-code/MiniNero/mrl_notes_v0.3.pdf
Normal file
BIN
source-code/MiniNero/mrl_notes_v0.3.pdf
Normal file
Binary file not shown.
1
source-code/MiniNero/nOfNMultisig.py
Normal file
1
source-code/MiniNero/nOfNMultisig.py
Normal file
|
@ -0,0 +1 @@
|
|||
import MiniNero
|
708
source-code/MiniNero/oldMiniNero.py
Normal file
708
source-code/MiniNero/oldMiniNero.py
Normal 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))))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
10
source-code/MiniNero/rct.py
Normal file
10
source-code/MiniNero/rct.py
Normal 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
|
||||
|
||||
|
5
source-code/MiniNero/scrap.py
Normal file
5
source-code/MiniNero/scrap.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
import ed25519
|
||||
import MiniNero
|
||||
import binascii
|
||||
|
||||
print(MiniNero.getHForCT())
|
1
source-code/MiniNero/test.hash
Normal file
1
source-code/MiniNero/test.hash
Normal file
File diff suppressed because one or more lines are too long
209
source-code/RingCT/Test.cpp
Normal file
209
source-code/RingCT/Test.cpp
Normal 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;
|
||||
}
|
842
source-code/RingCT/crypto-ops-data.c
Normal file
842
source-code/RingCT/crypto-ops-data.c
Normal 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)) */
|
5806
source-code/RingCT/crypto-ops.c
Normal file
5806
source-code/RingCT/crypto-ops.c
Normal file
File diff suppressed because it is too large
Load diff
150
source-code/RingCT/crypto-ops.h
Normal file
150
source-code/RingCT/crypto-ops.h
Normal 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 */
|
364
source-code/RingCT/crypto.cpp
Normal file
364
source-code/RingCT/crypto.cpp
Normal 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
258
source-code/RingCT/crypto.h
Normal 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)
|
32
source-code/RingCT/generic-ops.h
Normal file
32
source-code/RingCT/generic-ops.h
Normal 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); \
|
||||
} \
|
||||
}; \
|
||||
}
|
44
source-code/RingCT/hash-ops.h
Normal file
44
source-code/RingCT/hash-ops.h
Normal 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);
|
28
source-code/RingCT/initializer.h
Normal file
28
source-code/RingCT/initializer.h
Normal 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
|
201
source-code/RingCT/int-util.h
Normal file
201
source-code/RingCT/int-util.h
Normal 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
115
source-code/RingCT/keccak.c
Normal 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));
|
||||
}
|
29
source-code/RingCT/keccak.h
Normal file
29
source-code/RingCT/keccak.h
Normal 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
|
36
source-code/RingCT/param.h
Normal file
36
source-code/RingCT/param.h
Normal 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
114
source-code/RingCT/random.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
11
source-code/RingCT/random.h
Normal file
11
source-code/RingCT/random.h
Normal 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
|
||||
|
37
source-code/RingCT/rctMSig.cpp
Normal file
37
source-code/RingCT/rctMSig.cpp
Normal 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 {
|
||||
|
||||
}
|
68
source-code/RingCT/rctMSig.h
Normal file
68
source-code/RingCT/rctMSig.h
Normal 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
|
395
source-code/RingCT/rctOps.cpp
Normal file
395
source-code/RingCT/rctOps.cpp
Normal 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
144
source-code/RingCT/rctOps.h
Normal 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 */
|
540
source-code/RingCT/rctSigs.cpp
Normal file
540
source-code/RingCT/rctSigs.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
136
source-code/RingCT/rctSigs.h
Normal file
136
source-code/RingCT/rctSigs.h
Normal 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 */
|
||||
|
209
source-code/RingCT/rctTypes.cpp
Normal file
209
source-code/RingCT/rctTypes.cpp
Normal 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]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
259
source-code/RingCT/rctTypes.h
Normal file
259
source-code/RingCT/rctTypes.h
Normal 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 */
|
4
source-code/RingCT/runtest.bat
Normal file
4
source-code/RingCT/runtest.bat
Normal file
|
@ -0,0 +1,4 @@
|
|||
gtags.exe
|
||||
mingw32-make.exe clean
|
||||
mingw32-make.exe
|
||||
a.exe > .results
|
5
source-code/RingCT/runtest.sh
Normal file
5
source-code/RingCT/runtest.sh
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
gtags.exe
|
||||
make clean
|
||||
make
|
||||
./a.exe
|
1
source-code/RingCT/tasks.bat
Normal file
1
source-code/RingCT/tasks.bat
Normal file
|
@ -0,0 +1 @@
|
|||
%1
|
98
source-code/RingCT/varint.h
Normal file
98
source-code/RingCT/varint.h
Normal 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);
|
||||
}
|
||||
}
|
11
source-code/RingCT/warnings.h
Normal file
11
source-code/RingCT/warnings.h
Normal 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)
|
Loading…
Reference in a new issue