I know my algebra is rusty, but isn't the following an identity operation: multiplying an element of a GF by the cardinal of the field (the modulus)? I wrote a program to verify it but couldn't:
from ecpy.curves import Curve, Point # I use Python 2.7
def bin256(num):
"""binary conversion, returns a binary string, MSB first and LSB last"""
return '{:0256b}'.format(num)
def ec_multiply(P, d):
"""double-and-add algo. Index decreasing, same naming as Wikipedia:
P is a point on the curve
d is a long
returns P*d"""
Q = None
for bit in map(int, bin256(d)):
if Q is not None:
Q = Q + Q
if bit:
if Q is None:
Q = P
else:
Q = Q + P
return Q
def main():
"""Picks a random point on secp256k1 and multiply it by the modulus
of secp256k1 and print the result."""
cv = Curve.get_curve('secp256k1')
N = Point(0x65d5b8bf9ab1801c9f168d4815994ad35f1dcb6ae6c7a1a303966b677b813b00,
0xe6b865e529b8ecbf71cf966e900477d49ced5846d7662dd2dd11ccd55c0aff7f, cv)
MODULUS = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1
Q = ec_multiply(N, MODULUS)
print 'Q: %064x %064x' % (Q.x, Q.y)
if __name__ == '__main__':
main()
But I get a different point:
Q: d113d66bf911fbf026b2a3e24c96bba45ca2d2b130cbf312a36e584249153090 56cabae3704f1c5a7957cbb1d9e2f6198337c59c02b2974d32fb7501b7e287d2
I expected Q: 65d5b8bf..., e6b865e5... instead.
Any idea why multiplying by the modulus is not working in secp256k1? Thanks in advance.
Notes:
I am using the python elliptic curve library ecpy which just works, I've tested against another library (py_ecc, pure python) and I get consistent results.
The multiplication over secp256k1 uses the double-and-add algo from Wikipedia where the index is decreasing because I start from the MSB.
I use this excellent paper that explains everything about EC and how to implement them.
Related
I am currently working on a project replicating RSA key generation and testing using euclidean algorithm, extended euclidean algorithm to find the modular inverse of the value.
I used the Miller-Rabin test to choose two prime numbers, p and q.
After running the code, I am able to obtain Kpub and e, however Kpr returns as nan.
Please help!
#Euclidean Algorithm func
def EucAlgo(a, b):
if a==0:
return b
return EucAlgo(b % a,a)
def ExEucAlgo(a,b):
if a==0:
return b,0,1
gcd, s1, t1 = ExEucAlgo(b%a,a)
#gcd of a,b
s = t1 - (b/a) * s1
t = s1
return gcd, s, t
def ExEucAlgo_modInverse(a,b):
gcd, s, t = ExEucAlgo(b,a)
if (gcd == 1):
i = t % a
elif (gcd !=1):
print("There is no inverse modulo for the input.")
return i
def SqMul_ModularExpo(b, exp, n):
bin_exp = bin(exp)
base = b
for i in range (3, len(bin_exp)):
base = (base ** 2) % n
if(bin_exp[i]=='1'):
i+=1
base = (base * b) %n
return base
#RSA Key generation
p=9054583561027584891319616491815785011595937977633787663340258672121877196627062461308487615739189212918799813327175451021729047602129396754172486202100997
q=10115395220079214686776355235686624745626962891667413288473649946208213820942557513105240135405981494333016032659525466362014175268953946332375459648688023
n= p * q
phi_n= (p-1) * (q-1)
e= randint(1, phi_n - 1)
while((EucAlgo(e,phi_n)) !=1):
e = randint(1, (phi_n-1))
d = ExEucAlgo_modInverse(e,phi_n)
print(f"\nKpr={d}")
print(f"\nKpub=(n={n})\n \ne={e}")
The problem is that you are using float point division which will result in returning float a point which when dealing with large int can result in very large floats which python can't handle so the solution is to use integer division which means 5//2=2 not 2.5. The problem is that Now encrypting and decrypting data would result in wrong decryption. (You wont get 2 again) because of some bugs in your functions.
FIRST: use public exponent pf 65537(prime number) which is the default for all RSA implementations(see your browser certificates) rather than finding a random one. Then after calculating the extended Euclidean algorithm which is used to find modulo inverse you dont have to make any more calculations(just return this value if GCD is 1 otherwise raise an error or whatever).
Here is the complete code that works after removing some unneeded (functions, imports, and random public exponent) READ comments.
def EucAlgo(a, b):
if a == 0:
return b
return EucAlgo(b % a, a)
def ExEucAlgo(a,b):
if a==0:
return b, 0, 1
gcd, s1, t1 = ExEucAlgo(b%a, a)
# You dont use / use // to make integer division
s = t1 - (b//a) * s1
t = s1
return gcd, s, t
def ExEucAlgo_modInverse(a,b):
gcd, s, t = ExEucAlgo(a, b)
if (gcd == 1):
# Just return s which is the inverse of public exponent
return s
elif (gcd != 1):
# I think it's better to raise an error but it's up to you
print("There is no inverse modulo for the input.")
#RSA Key generation
p = 9054583561027584891319616491815785011595937977633787663340258672121877196627062461308487615739189212918799813327175451021729047602129396754172486202100997
q = 10115395220079214686776355235686624745626962891667413288473649946208213820942557513105240135405981494333016032659525466362014175268953946332375459648688023
n = p * q
phi_n = (p-1) * (q-1)
# Just use fixed prime public exponent rather than trying fixed ones
e = 65537
d = ExEucAlgo_modInverse(e, phi_n)
print(f"\nKpr={d}")
print(f"\nKpub=(n={n})\n \ne={e}")
# Try to encrypt and decrypt 36
ciphertext = pow(36, e, n)
print("Encrypted data {}".format(ciphertext))
print("Decrypted data is {}".format(pow(ciphertext, d, n)))
Programming in python with numpy and sympy, and my attempts to use derivatives in my code are falling flat. I frequently get either
"TypeError: 'Add' object is not callable"
and,
"ValueError: First variable cannot be a number: 1".
This is for a program meant to define Newton's Method for solving a root-finding problem. The sample equation I've used is 1/x+log(x)-2. I mention this because I've had a few issues with numpy's log function, as well. I think my problem has to do with the diff I'm using, as I'm not entirely certain how to use it to return an actual value, and the literature I've read on it isn't incredibly helpful.
def newton(p0, f, n, t):
global p
p = 0
for i in range(1, n+1):
p = p0 - f(p0)/diff(f(x),p0)
if abs(p-p0) < t:
return p
p0 = p
i = i + 1
return f"The method failed after {n} iterations. The procedure was unsuccessful."
print(newton(p0=1, f=1/x+log(x)-2, n=10, t=5e-324))
I'm at least expecting a number, but I'm getting the errors I describe above.
there are two problems in your code,
the first is the parameter f in your function should have a 'function' input, which means f=lambda x: 1/x+log(x)-2,
the second is p = p0 - f(p0)/diff(f(x),p0). If I understand correctly, you are expecting the diff function to perform as a derivation function, however, it's not. Maybe you can define your own derivation function:
def df(f, x):
h = 1e-5
return (f(x+h)-f(x))/h
then you can write p = p0 - f(p0)/df(f, p0)
so the whole code can be written as below:
def newton(p0, f, n, t):
global p
p = 0
for i in range(1, n+1):
def df(f, x):
h = 1e-5
return (f(x+h)-f(x))/h
p = p0 - f(p0)/df(f, p0)
if abs(p-p0) < t:
return p
p0 = p
i = i + 1
return f"The method failed after {n} iterations. The procedure was unsuccessful."
print(newton(p0=1, f=lambda x: 1/x+log(x)-2, n=10, t=5e-324))
I try to do a simple division of polynomials in two variables using sage.
Unfortunately, I get an unexpected result, as is illustrated in the code below.
I tried several different ways to instantiate the ring and its variables, but
the result stays the same. Using the %-operator to get a rest of a division yields the same results. Any ideas?
R, (x, y) = PolynomialRing(RationalField(), 2, 'xy').objgens()
t = x^2*y^2 + x^2*y - y + 1
f1 = x*y^2 + x
f2 = x*y - y^3
(q, r) = t.quo_rem(f1)
print "quotient:", q, "reminder:", r
assert q == x and r == x^2*y-x^2-y+1
(q, r) = r.quo_rem(f2) # error, expected q = x, r = -x^2+x*y^3-y+1
print "quotient:", q, "reminder:", r
assert q == x and r == -x^2+x*y^3-y+1
Output:
quotient: x reminder: x^2*y - x^2 - y + 1
quotient: 0 reminder: x^2*y - x^2 - y + 1
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-8-861e8a9d1112> in <module>()
10 (q, r) = r.quo_rem(f2) # error, expected q = x, r = -x^2+x*y^3-y+1
11 print "quotient:", q, "reminder:", r
---> 12 assert q == x and r == -x**Integer(2)+x*y**Integer(3)-y+Integer(1)
AssertionError:
Division of multivariate polynomials: term orders
The result of division of multivariable polynomials depends on the chosen order of monomials, as is explained in Wikipedia. For the present, it suffices to say that the quotient from dividing P by Q is nonzero if and only if P contains a monomial that is divisible by the leading monomial of Q with respect to the chosen order.
By default, polynomial rings in Sage use the degree-reverse lexicographic order (degrevlex for short), in which monomials are first sorted by total degree, and then lexicographically within each degree. You can check this by using R.term_order(). And here is the list of term orders.
In the degrevlex order, y^3 precedes x*y because it has higher total degree. And since x^2*y-x^2-y+1 does not have a monomial divisible by y^3, you get zero quotient.
Buggy quo_rem
Your expected results are consistent with the lexicographic (lex) order of monomials. So, it would seem that the fix is to prescribe lexicographic term order when constructing R:
R.<x,y> = PolynomialRing(QQ, 2, 'xy', order='lex')
Unfortunately, quo_rem ignores the term order of R and still uses degrevlex. This appears to be a bug, either in the way Sage communicates with Singular, or in Singular itself (the Quotient command is deprecated).
Workaround
Meanwhile, there is a workaround: use the reduce command instead of quo_rem, as it respects the term order of R. For example:
R.<x,y> = PolynomialRing(QQ, 2, 'xy', order='lex')
a = x^2*y-x^2-y+1
f2 = x*y-y^3
r = a.reduce(Ideal([f2]))
q = (a-r)/f2
This returns r = -x^2 + x*y^3 - y + 1 and q = x.
I need to calculate the arcsine function of small values that are under the form of mpmath's "mpf" floating-point bignums.
What I call a "small" value is for example e/4/(10**7) = 0.000000067957045711476130884...
Here is a result of a test on my machine with mpmath's built-in asin function:
import gmpy2
from mpmath import *
from time import time
mp.dps = 10**6
val=e/4/(10**7)
print "ready"
start=time()
temp=asin(val)
print "mpmath asin: "+str(time()-start)+" seconds"
>>> 155.108999968 seconds
This is a particular case: I work with somewhat small numbers, so I'm asking myself if there is a way to calculate it in python that actually beats mpmath for this particular case (= for small values).
Taylor series are actually a good choice here because they converge very fast for small arguments. But I still need to accelerate the calculations further somehow.
Actually there are some problems:
1) Binary splitting is ineffective here because it shines only when you can write the argument as a small fraction. A full-precision float is given here.
2) arcsin is a non-alternating series, thus Van Wijngaarden or sumalt transformations are ineffective too (unless there is a way I'm not aware of to generalize them to non-alternating series).
https://en.wikipedia.org/wiki/Van_Wijngaarden_transformation
The only acceleration left I can think of is Chebyshev polynomials. Can Chebyshev polynomials be applied on the arcsin function? How to?
Can you use the mpfr type that is included in gmpy2?
>>> import gmpy2
>>> gmpy2.get_context().precision = 3100000
>>> val = gmpy2.exp(1)/4/10**7
>>> from time import time
>>> start=time();r=gmpy2.asin(val);print time()-start
3.36188197136
In addition to supporting the GMP library, gmpy2 also supports the MPFR and MPC multiple-precision libraries.
Disclaimer: I maintain gmpy2.
Actually binary splitting does work very well, if combined with iterated argument reduction to balance the number of terms against the size of the numerators and denominators (this is known as the bit-burst algorithm).
Here is a binary splitting implementation for mpmath based on repeated application of the formula atan(t) = atan(p/2^q) + atan((t*2^q-p) / (2^q+p*t)). This formula was suggested recently by Richard Brent (in fact mpmath's atan already uses a single invocation of this formula at low precision, in order to look up atan(p/2^q) from a cache). If I remember correctly, MPFR also uses the bit-burst algorithm to evaluate atan, but it uses a slightly different formula, which possibly is more efficient (instead of evaluating several different arctangent values, it does analytic continuation using the arctangent differential equation).
from mpmath.libmp import MPZ, bitcount
from mpmath import mp
def bsplit(p, q, a, b):
if b - a == 1:
if a == 0:
P = p
Q = q
else:
P = p * p
Q = q * 2
B = MPZ(1 + 2 * a)
if a % 2 == 1:
B = -B
T = P
return P, Q, B, T
else:
m = a + (b - a) // 2
P1, Q1, B1, T1 = bsplit(p, q, a, m)
P2, Q2, B2, T2 = bsplit(p, q, m, b)
T = ((T1 * B2) << Q2) + T2 * B1 * P1
P = P1 * P2
B = B1 * B2
Q = Q1 + Q2
return P, Q, B, T
def atan_bsplit(p, q, prec):
"""computes atan(p/2^q) as a fixed-point number"""
if p == 0:
return MPZ(0)
# FIXME
nterms = (-prec / (bitcount(p) - q) - 1) * 0.5
nterms = int(nterms) + 1
if nterms < 1:
return MPZ(0)
P, Q, B, T = bsplit(p, q, 0, nterms)
if prec >= Q:
return (T << (prec - Q)) // B
else:
return T // (B << (Q - prec))
def atan_fixed(x, prec):
t = MPZ(x)
s = MPZ(0)
q = 1
while t:
q = min(q, prec)
p = t >> (prec - q)
if p:
s += atan_bsplit(p, q, prec)
u = (t << q) - (p << prec)
v = (MPZ(1) << (q + prec)) + p * t
t = (u << prec) // v
q *= 2
return s
def atan1(x):
prec = mp.prec
man = x.to_fixed(prec)
return mp.mpf((atan_fixed(man, prec), -prec))
def asin1(x):
x = mpf(x)
return atan1(x/sqrt(1-x**2))
With this code, I get:
>>> from mpmath import *
>>> mp.dps = 1000000
>>> val=e/4/(10**7)
>>> from time import time
>>> start = time(); y1 = asin(x); print time() - start
58.8485069275
>>> start = time(); y2 = asin1(x); print time() - start
8.26498985291
>>> nprint(y2 - y1)
-2.31674e-1000000
Warning: atan1 assumes 0 <= x < 1/2, and the determination of the number of terms might not be optimal or correct (fixing these issues is left as an exercise to the reader).
A fast way is to use a pre-calculated look-up table.
But if you look at e.g. a Taylor series for asin;
def asin(x):
rv = (x + 1/3.0*x**3 + 7/30.0*x**5 + 64/315.0*x**7 + 4477/22680.0*x**9 +
28447/138600.0*x**11 + 23029/102960.0*x**13 +
17905882/70945875.0*x**15 + 1158176431/3958416000.0*x**17 +
9149187845813/26398676304000.0*x**19)
return rv
You'll see that for small values of x, asin(x) ≈ x.
In [19]: asin(1e-7)
Out[19]: 1.0000000000000033e-07
In [20]: asin(1e-9)
Out[20]: 1e-09
In [21]: asin(1e-11)
Out[21]: 1e-11
In [22]: asin(1e-12)
Out[22]: 1e-12
E.g. for the value us used:
In [23]: asin(0.000000067957045711476130884)
Out[23]: 6.795704571147624e-08
In [24]: asin(0.000000067957045711476130884)/0.000000067957045711476130884
Out[24]: 1.0000000000000016
Of course it depends on whether this difference is relevant to you.
I've been working on Project euler Problem 57 (Love the site!). For this problem a conversion is required between a finite continued fraction and a normal fraction. I devised an algorithm that basically takes the inverse of the last number in a list, add it to the next-to-last and continues until the final fraction remains. For problem 67 it worked maverlously, but this time it stops working after the second iteration (I have to perform the algorithm on multiple continued fractions).
This is the piece of code (I used an external module, namely sympy):
import time
from sympy import *
from sympy import fraction, Rational, Symbol
def cont_fract_to_fraction(cont_frac_list):
a=cont_frac_list[-1]
b=cont_frac_list[-2]
new_reduced=Rational(b,1)+ Rational(1,a)
cont_frac_list[-2]=new_reduced
del cont_frac_list[-1]
if len(cont_frac_list)==1:
print cont_frac_list #To check
return cont_frac_list
else:
cont_fract_to_fraction(cont_frac_list)
def numerator_higher_denominator(fraction):
num=str(fraction[0])
den=str(fraction[1])
if len(num)>len(den):
return 1
else:
return 0
start=time.time()
tally=0
for k in xrange (1, 101):
sqrt_eval=[1]
for x in xrange (1, k+2):
sqrt_eval.append(2)
sqrt_eval=cont_fract_to_fraction(sqrt_eval)
print sqrt_eval ##To double check
#fraction_result=fraction(soln[0]) To introduce later
#tally+=numerator_higher_denominator(fraction_result) To introduce later
elapsed=time.time()-start
print "Solution: ", tally, "Solved in: ", elapsed
I basically test just to see if it gets all the final fraction and the print from the function, before the return, gives the answer, but the print after I assigned the value to sqrt_eval prints None. Here is a test run:
###Test run####
[3/2] #--> function print
[3/2] #--> sqrt_eval print
[7/5]
None
[17/12]
None
[41/29]
None
[99/70]
None
[239/169]
None
[577/408]
None
[1393/985]
None
[3363/2378]
None
[8119/5741]
None
[19601/13860]
None
I've been searching thouroughly for an answer and can't quite find one. Help me debug this, if you can, without altering the code much.
The fractions module makes short work of this problem:
>>> from fractions import Fraction
>>> def normal_fraction(continued_fraction):
n = Fraction(0)
for d in continued_fraction[:0:-1]:
n = 1 / (d + n)
return continued_fraction[0] + n
>>> cf = [3,7,15,1,292,1,1,1,2,1,3,1]
>>> normal_fraction(cf)
Fraction(5419351, 1725033)
>>> float(_)
3.1415926535898153
If you like functional programming and concise code, the above logic can be expressed in a one-liner using reduce():
>>> cf[0] + reduce(lambda d, n: 1 / (d + n), cf[:0:-1], Fraction(0))
Fraction(5419351, 1725033)
And here is a version that doesn't use Fraction. It will work even on very old versions of Python:
def normal_fraction(continued_fraction):
n, d = 0, 1
for a in continued_fraction[:0:-1]:
n, d = d, a*d + n
return continued_fraction[0]*d + n, d
This doesn't answer your question, but there are some formulas on Wikipedia that might let you compute this more efficiently.