research-lab/source-code/MiniNero/oldMiniNero.py

709 lines
25 KiB
Python
Raw Normal View History

2016-02-05 20:20:44 +00:00
########################################################################
# 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))))