Python Forum

Full Version: Getting int from file instead of randomgenerator
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
So this is some code I got off the net. What I'm trying to do is simple I think. What this is, is a Elliptic Curve Cryptography using the BitCoin curve, SECG secp256k1. I'm trying to make it encrypt a key from a file instead of an integer generated by the random number generator.
I was thinking of maybe adding
file = open('key.txt','r')
Will something like that work, or will it still be deriving the encryption from the random number generator?
from math import log
from copy import copy
from time import time # timing
from fractions import gcd # Greatest Common Denominator
from random import SystemRandom # cryptographic random byte generator
rand=SystemRandom() # create strong random number generator

# Convert a string with hex digits, colons, and whitespace to a long integer
def hex2int(hexString):
	return int("".join(hexString.replace(":","").split()),16)

# Half the extended Euclidean algorithm:
#    Computes   gcd(a,b) = a*x + b*y  
#    Returns only gcd, x (not y)
# From http://rosettacode.org/wiki/Modular_inverse#Python
def half_extended_gcd(aa, bb):
	lastrem, rem = abs(aa), abs(bb)
	x, lastx = 0, 1
	while rem:
		lastrem, (quotient, rem) = rem, divmod(lastrem, rem)
		x, lastx = lastx - quotient*x, x
	return lastrem, lastx 

# Modular inverse: compute the multiplicative inverse i of a mod m:
#     i*a = a*i = 1 mod m
def modular_inverse(a, m):
	g, x = half_extended_gcd(a, m)
	if g != 1:
		raise ValueError
	return x % m


# An elliptic curve has these fields:
#   p: the prime used to mod all coordinates
#   a: linear part of curve: y^2 = x^3 + ax + b
#   b: constant part of curve
#   G: a curve point (G.x,G.y) used as a "generator"
#   n: the order of the generator
class ECcurve:
	def __init__(self):
		return

	# Prime field multiplication: return a*b mod p
	def field_mul(self,a,b):
		return (a*b)%self.p

	# Prime field division: return num/den mod p
	def field_div(self,num,den):
		inverse_den=modular_inverse(den%self.p,self.p)
		return self.field_mul(num%self.p,inverse_den)

	# Prime field exponentiation: raise num to power mod p
	def field_exp(self,num,power):
		return pow(num%self.p,power,self.p)

	# Return the special identity point
	#   We pick x=p, y=0
	def identity(self):
		return ECpoint(self,self.p,0)

	# Return true if point Q lies on our curve
	def touches(self,Q):
		y2=self.field_exp(Q.y,2)
		x3ab=(self.field_mul((Q.x*Q.x)%self.p+self.a,Q.x)+self.b)%self.p
		return y2==x3ab

	# Return the slope of the tangent of this curve at point Q
	def tangent(self,Q):
		return self.field_div(Q.x*Q.x*3+self.a,Q.y*2)

	# Return the (x,y) point where this line intersects our curve
	#  Q1 and Q2 are two points on the line of slope m
	def line_intersect(self,Q1,Q2,m):
		v=(Q1.y + self.p - (m*Q1.x)%self.p)%self.p
		x=(m*m + self.p-Q1.x + self.p-Q2.x)%self.p
		y=(self.p-(m*x)%self.p + self.p-v)%self.p
		return ECpoint(self,x,y)

	# Return a doubled version of this elliptic curve point
	def double(self,Q):
		if (Q.x==self.p): # doubling the identity
			return Q
		return self.line_intersect(Q,Q,self.tangent(Q))

	# Return the "sum" of these elliptic curve points
	def add(self,Q1,Q2):
		# Identity special cases
		if (Q1.x==self.p): # Q1 is identity
			return Q2
		if (Q2.x==self.p): # Q2 is identity
			return Q1

		# Equality special cases
		if (Q1.x==Q2.x): 
			if (Q1.y==Q2.y): # adding point to itself
				return self.double(Q1)
			else: # vertical pair--result is the identity
				return self.identity()

		# Ordinary case
		m=self.field_div(Q1.y+self.p-Q2.y,Q1.x+self.p-Q2.x)
		return self.line_intersect(Q1,Q2,m)

	# "Multiply" this elliptic curve point Q by the integer m
	#    Often the point Q will be the generator G
	def mul(self,Q,m):
		R=self.identity() # return point
		while m!=0:  # binary multiply loop
			if m&1: # bit is set
				# print("  mul: adding Q to R =",R);
				R=self.add(R,Q)
			m=m>>1
			if (m!=0):
				# print("  mul: doubling Q =",Q);
				Q=self.double(Q)
		
		return R

# A point on an elliptic curve: (x,y)
class ECpoint:
	"""A point on an elliptic curve (x,y)"""
	def __init__(self,curve, x,y):
		self.curve=curve
		self.x=x
		self.y=y
		if not x==curve.p and not curve.touches(self):
			print(" ECpoint left curve: ",x,",",y)

	# "Add" this point to another point on the same curve
	def add(self,Q2):
		return self.curve.add(self,Q2)

	# "Multiply" this point by a scalar
	def mul(self,m):
		return self.curve.mul(self,m)

	# Print this ECpoint
	def __str__(self):
		if (self.x==self.curve.p):
			return "identity_point"
		else:
			return "("+str(self.x)+", "+str(self.y)+")"


# This is the BitCoin elliptic curve, SECG secp256k1
#   See http://www.secg.org/SEC2-Ver-1.0.pdf
secp256k1=ECcurve()
secp256k1.p=hex2int("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
secp256k1.a=0 # it's a Koblitz curve, with no linear part
secp256k1.b=7 
secp256k1.n=hex2int("FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141");

# SEC's "04" means they're representing the generator point's X,Y parts explicitly.
#  The compressed "02" form means storing only x (you compute Y)
secp256k1.G=ECpoint(curve=secp256k1,
  x = hex2int("79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798"),
  y = hex2int("483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8")
);


#################
# Test program:
curve=secp256k1

Q=curve.G
print("Generator touches curve? ",curve.touches(Q));
print("Tangent of generator: ",curve.tangent(Q));

for i in range(2,10):
	Q=Q.add(curve.G) # repeatedly add generator
	print("Curve point ",i,Q);

	J=curve.mul(curve.G,i) # direct jump
	if (J.x!=Q.x or J.y!=Q.y):
		print("    -> MULTIPLY MISMATCH: ",J.x,",",J.y);


start=time()

# Diffie-Hellman key exchange
A_secret=rand.getrandbits(256)%curve.p
A_public=curve.mul(curve.G,A_secret);

B_secret=rand.getrandbits(256)%curve.p
B_public=curve.mul(curve.G,B_secret);

# A and B would exchange public points here

AB_shared=curve.mul(A_public,B_secret); # B computes this
BA_shared=curve.mul(B_public,A_secret); # A computes this

if (AB_shared.x == BA_shared.x):
	print("ECDH key exchange success! ",AB_shared);

print("ECDH elapsed=",time()-start," seconds")
The Python RNG is terrible for secure encryption. I've heard that the cryptography module is a bit better.

pip3 install cryptography
You can create a seed from the time clock:
the arguments in randint are starting and ending range
import random
import time
random.seed(time.clock())
print(random.randint(0, 20000))
What if I don't want it to be a random integer. It works fairly fine if I get rid of the
rand=SystemRandom() # create strong random number generator
and replace it with
rand = open('key.txt', 'r')
. The problem is when it gets to the "Diffie-Hellman key exchange" I get this error:
 A_secret=rand.getrandbits(256)%curve.p
AttributeError: 'file' object has no attribute 'getrandbits'
Here is the output in its entirety, if anyone was interested in what it looked like.

/usr/bin/python2.7 /home/b/Downloads/ECC_bitcoin.py
('Generator touches curve? ', True)
Traceback (most recent call last):
('Tangent of generator: ', 91914383230618135761690975197207778399550061809281766160147273830617914855857L)
  File "/home/b/Downloads/ECC_bitcoin.py", line 186, in <module>
('Curve point ', 2, <__main__.ECpoint instance at 0x7fc84bd13f80>)
    A_secret=rand.getrandbits(256)%curve.p
AttributeError: 'file' object has no attribute 'getrandbits'
('Curve point ', 3, <__main__.ECpoint instance at 0x7fc84bd1b050>)
('Curve point ', 4, <__main__.ECpoint instance at 0x7fc84bd13f80>)
('Curve point ', 5, <__main__.ECpoint instance at 0x7fc84bd1b0e0>)
('Curve point ', 6, <__main__.ECpoint instance at 0x7fc84bd1b248>)
('Curve point ', 7, <__main__.ECpoint instance at 0x7fc84bd13f80>)
('Curve point ', 8, <__main__.ECpoint instance at 0x7fc84bd1b170>)
('Curve point ', 9, <__main__.ECpoint instance at 0x7fc84bd13f80>)
You don't have to use:
print(random.randint(0, 20000))
There are many other options: https://docs.python.org/3.6/library/random.html
The seed was what I was showing, the int example was just extra
Is it because I need to get the string from the file and convert it to an integer? I just don't want it to be a random seed. I'm trying to get it to use a seed of my choosing. Instead of having the random number generator send an integer through the encryption algorithm. So that I may inspect the output of the integer that I chose, in the form of a public key (IE: 0x7fc84bd13f80).

Would this work?

x = []
file_in = open('key.txt', 'r')
for y in file_in.read().split('\n'):
    x.append(float(y))
Assuming your file is a collection of numbers, each in its own line, you'd be better off with:

x = []
with open('key.txt', 'r') as file:
    for line in file:
        number = float(line.rstrip('\n'))
        x.append(number)
You mentioned integers in previous post, so are you sure you want to have floats appended to x?
(Jan-24-2018, 09:59 PM)j.crater Wrote: [ -> ]Assuming your file is a collection of numbers, each in its own line, you'd be better off with:

x = []
with open('key.txt', 'r') as file:
    for line in file:
        number = float(line.rstrip('\n'))
        x.append(number)
You mentioned integers in previous post, so are you sure you want to have floats appended to x?

Honestly this is where my noobness is going to show the most.. So I apologize. I'm still teaching myself python since the last time I posted on these forums, and this is just a new idea I had. Anyway, no I'm not sure that append is what I'm trying to do. I guess append means I want to add something to a list, and I suppose that isn't what I'm trying to do. I'm just trying to read a string from a file and then run that string through the cryptographic curve. Right now from what I can tell, the blog I got this particular code from has it set up to run from a seed generated by a random generator.
This person created exactly what I'm trying to create basically.here I could just use theirs, but I'd like to make my own. Also I can't get PyQt5 to work correctly for me so its kinda useless for me at the moment.
If your text file only has one string (the integer you want), then this will suffice:
x = 0
with open('key.txt', 'r') as file:
    number = file.readline().rstrip('\n')
    x = int(number)
It is good you decided to do things on your own as part of learning process. You can post PyQt related questions in the GUI subforum.
Pages: 1 2