Hi I am new to encryption algorithms and am a little confused by the terminology and what to choose for which situation. For now I don't need the most secure algorithm but it should have the following properties:
A shared secret key, that encrypts/decrypts the message (two way).
The Cipher should be the same if same text for encryption has been used.
I used the Fernet algorithm in Python, however the Ciphertext is always different. and therefore not suitable for my needs. Is there an algorithm similar to Fernet but without the Salt?
Assuming you're using the cryptography module (which you should): Instead of using generate_key(), build the key and pass it to the Fernet constructor.
Check this link for the precise example: https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet
Additionally, check https://www.crypto101.io/ if you haven't yet.
Actually there's no ready algorithm do what you're asking for "at lease that what I know".
But in the past I've wrote a GUI chat room with a real server and real clients in python.
And I've wrote a basic encryption/decryption algorithm to pass the data encrypted "like messages".
you can use it if you want cuz I've never used that server I made it just for fun ;).
The algorithm:
from cryptography.fernet import Fernet
CODES_KEY = b'LYsrKDiTRNJDm3g_h25GW0uyUzPTk8l8G02hcPM_d_U='
def encryption(msg):
'''
Encryption Func
'''
class RSA:
'''
RSA Encryption Func
'''
def __init__(self):
self.e = self.d = self.p = self.q = self.phi = 0
def __egcd(self, a, b):
if a == 0:
return (b, 0, 1)
g, y, x = self.__egcd(b % a, a)
return (g, x - (b // a) * y, y)
def __modinv(self, a, m):
g, x, _ = self.__egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
return x % m
def encrypt(self, m, key_pair=None):
'''
Encrypting Func
'''
if key_pair is None:
key_pair[0] = self.e
key_pair[1] = self.n
return pow(m, key_pair[0], key_pair[1])
def generate_keys(self, p, q, e=3):
'''
Generating Keys Func
'''
self.p = p
self.q = q
self.n = self.p * self.q
self.phi = (self.p - 1) * (self.q - 1)
self.e = e
self.d = self.__modinv(self.e, self.phi)
if self.phi % self.e == 0:
raise Exception('invalid values for p and q')
def get_public_key(self):
'''
Getting PublicKey Func
'''
return self.e, self.n
rsa = RSA()
# Two 1024-bit primes
rsa.generate_keys(17055899557196527525682810191339089909014331959812898993437334555169285087976951946809555356817674844913188193949144165887100694620944167618997411049745043243260854998720061941490491091205087788373487296637817044103762239946752241631032791287021875863785226376406279424552454153388492970310795447866569138481,
171994050316145327367864378293770397343246561147593187377005295591120640129800725892235968688434055779668692095961697434700708550594137135605048681344218643671046905252163983827396726536078773766353616572531688390937410451433665914394068509329532352022301339189851111636176939179510955519440490431177444857017)
int_message = []
for i in msg:
int_message.append(ord(i))
codes = []
for i in int_message:
codes.append(len(str(i)))
message = int(''.join([str(x) for x in int_message]))
# Encrypting
encrypted_message = rsa.encrypt(message, key_pair=rsa.get_public_key())
f = Fernet(CODES_KEY)
encrypted_codes = f.encrypt(str(codes).encode())
return encrypted_message, encrypted_codes
def decryption(msg, codes):
'''
Decryption Func
'''
class RSA:
'''
RSA Decryption Func
'''
def __init__(self):
self.e = self.d = self.p = self.q = self.phi = 0
def __egcd(self, a, b):
if a == 0:
return (b, a, 1)
g, y, x = self.__egcd(b % a, a)
return (g, x - (b // a) * y, y)
def __modinv(self, a, m):
g, x, _ = self.__egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
return x % m
def decrypt(self, c, key_pair=None):
'''
Decrypting Func
'''
if key_pair is None:
key_pair[0] = self.d
key_pair[1] = self.n
return pow(c, key_pair[0], key_pair[1])
def generate_keys(self, p, q, e=3):
'''
Generating Keys Func
'''
self.p = p
self.q = q
self.n = self.p * self.q
self.phi = (self.p - 1) * (self.q - 1)
self.e = e
self.d = self.__modinv(self.e, self.phi)
if self.phi % self.e == 0:
raise Exception('invalid values for p and q')
def get_private_key(self):
'''
Getting Private Key Func
'''
return self.d, self.n
rsa = RSA()
# Two 1024-bit primes
rsa.generate_keys(17055899557196527525682810191339089909014331959812898993437334555169285087976951946809555356817674844913188193949144165887100694620944167618997411049745043243260854998720061941490491091205087788373487296637817044103762239946752241631032791287021875863785226376406279424552454153388492970310795447866569138481,
171994050316145327367864378293770397343246561147593187377005295591120640129800725892235968688434055779668692095961697434700708550594137135605048681344218643671046905252163983827396726536078773766353616572531688390937410451433665914394068509329532352022301339189851111636176939179510955519440490431177444857017)
# Decrypting
f = Fernet(CODES_KEY)
# set_trace()
decrypted_message = str(rsa.decrypt(int(msg), key_pair=rsa.get_private_key()))
decrypted_codes = f.decrypt(codes).decode()
decrypted_message = list(decrypted_message)
original_codes = []
for i in decrypted_codes:
if i not in ['[', ']', ',', ' ']:
original_codes.append(int(i))
original_message = ""
for _, value in enumerate(original_codes):
handler = ""
for i in decrypted_message[:value]:
handler += i
original_message += chr(int(handler))
decrypted_message = decrypted_message[value:]
return original_message
def main():
message = "Hi, This is a secret message"
encrypted_message, encrypted_codes = encryption(message)
decrypted_message = decryption(encrypted_message, encrypted_codes)
print(decrypted_message)
if __name__ == '__main__':
main()
Sorry if it's a mess but I'm just 17 years old bro :) !
Maybe you can optimize it more I've wrote this when i was new to python.
you can always generate new "CODES_KEY" by running this in python:
from cryptography.fernet import Fernet
f = Fernet
print(f.generate_key())
EDIT: I wrote this as an RSA but then changed the code, this is why it's named RSA but it's not :)
Related
I was wondering if there is a way for a class to define a method that behaves like a static method (can be called without an instance variable) and a regular method (can be called with an instance variable).
Im making an RSA module that would help me solve RSA problems, the initialization goes like this:
class RSA:
def __init__(self, n: int, e: int, c: int, p=None, q=None, phi=None):
self.n = n
self.e = e
self.c = c
self.p = p
self.q = q
assert p == None or gmpy2.is_prime(p), 'p must be prime'
assert q == None or gmpy2.is_prime(q), 'q must be prime'
self.phi = phi
and in that class, there is a method that would factorize n into p and q which goes like this (the algorithm used is irrelevant so I wont bother explaining):
def fermat_factorization(self, n=None):
if n == None:
n = self.n
t_ = gmpy2.isqrt(n)+1
counter = 0
t = t_ + counter
temp = gmpy2.isqrt((t * t) - n)
while((temp * temp) != ((t * t) - n)):
counter += 1
t = t_ + counter
temp = gmpy2.isqrt((t * t) - n)
s = temp
p = t + s
q = t - s
return p, q
that implementation does not work. What I wanted to do is for that method to be dynamic, i.e. can be called externally by simply
p, q = RSA.fermat_factorization(n) # n is some large number
yet can also be called on an instance like:
s1 = RSA(n, 65537, c) # c and n is some large number
p, q = s1.fermat_factorization() # without specifying n because it is already an instance attribute
In python, you use modules for that kind of stuff, not classes:
in rsa.py
def fermat_factorization(n):
"""Ordinary function"""
class RSA:
def fermat_factorization(self):
"""Method"""
return fermat_factorization(self.n)
somewhere else:
import rsa
x = rsa.fermat_factorization(100)
obj = rsa.RSA(...)
y = obj.fermat_factorization()
Having a single function that behaves some way or another depending on how it's called is a recipe for disaster. Don't do that.
I was following this tutorial and after creating the classes I still cannot import the desired module. The code I used:
import numpy as np
import sys
class ForwardEuler:
def __init__(self, f):
# test that f is a function
if not callable(f):
raise TypeError('f is %s, not a function' % type(f))
self.f = f
def set_initial_condition(self, U0):
self.U0 = float(U0)
def solve(self, time_points):
"""Compute u for t values in time_points list."""
self.t = np.asarray(time_points)
self.u = np.zeros(len(time_points))
self.u[0] = self.U0
for k in range(len(self.t)-1):
self.k = k
self.u[k+1] = self.advance()
return self.u, self.t
def advance(self):
"""Advance the solution one time step."""
u, f, k, t = self.u, self.f, self.k, self.t
dt = t[k+1] - t[k]
unew = u[k] + dt*f(u[k], t[k])
return unew
class ODESolver:
def __init__(self, f):
self.f = f
def advance(self):
"""Advance solution one time step."""
raise NotImplementedError # implement in subclass
def set_initial_condition(self, U0):
self.U0 = float(U0)
def solve(self, time_points):
self.t = np.asarray(time_points)
self.u = np.zeros(len(self.t))
# Assume that self.t[0] corresponds to self.U0
self.u[0] = self.U0
# Time loop
for k in range(n-1):
self.k = k
self.u[k+1] = self.advance()
return self.u, self.t
def advance(self):
raise NotImplemtedError # to be impl. in subclasses
class ForwardEuler(ODESolver):
def advance(self):
u, f, k, t = self.u, self.f, self.k, self.t
dt = t[k+1] - t[k]
unew = u[k] + dt*f(u[k], t)
return unew
Now, I want from ODESolver import ForwardEuler, but there is no module named ODESolver. How do I create it? I suppose there must be something with if __name__ == '__main__': and then the classes underneath, but that didn't work either.
the name of the file.py where you are writting this code is the name of module
you must name it ODESolver
then you can do
from ODESolver import ForwardEuler
I'm trying to implement Shamir Secret Sharing Sceme in python,i need to ask the user for a password and then obtain a hash code with sha256, but when I try to use that as a parameter for AES it says that the length of the key must be 16, 24 or 32 bits, doesn´t sha256 return a 32 byte string?
Here's my code:
import getpass
import hashlib
import random
import operator
from functools import reduce
import sys
import os
from Crypto.Cipher import AES
p= 208351617316091241234326746312124448251235562226470491514186331217050270460481
points= []
## Class Prime
#
# Class that represents integers modulo p, it is built from a non negative integer
# , comes with its own implementations of basic operations like sum, multiplication
# and division, the division is calculated ith the extended euclidean algorithm.
class Prime(object):
## The constructor
def __init__(self, n):
self.n = n % p
def __add__(self, other): return Prime(self.n + other.n)
def __sub__(self, other): return Prime(self.n - other.n)
def __mul__(self, other): return Prime(self.n * other.n)
def __pow__(self, x): return Prime(self.n**x)
def __truediv__(self, other): return self * other.inverse()
def __div__(self, other): return self * other.inverse()
def __neg__(self): return Prime(-self.n)
def __eq__(self, other): return isinstance(other, Prime) and self.n == other.n
def __abs__(self): return abs(self.n)
def __str__(self): return str(self.n)
def __divmod__(self, divisor):
q,r = divmod(self.n, divisor.n)
return (Prime(q), Prime(r))
def EuclideanAlgorithm(a, b):
if abs(b) > abs(a):
(x,y,d) = EuclideanAlgorithm(b, a)
return (y,x,d)
if abs(b) == 0:
return (1, 0, a)
x1, x2, y1, y2 = 0, 1, 1, 0
while abs(b) > 0:
q, r = divmod(a,b)
x = x2 - q*x1
y = y2 - q*y1
a, b, x2, x1, y2, y1 = b, r, x1, x, y1, y
return (x2, y2, a)
def inverse(self):
(x,y,d)= EuclideanAlgorithm(self.n, p)
return Prime(x)
## Class Polynomial
#
# Class that represents a polynomial, it is built from a list of coefficients
# comes with a call method to evaluate the polynomial in a value "x", and has
# a reduced lagrange method that gets the constant value of a polynomial from
# a set of points
class Polynomial(object):
## The constructor
def __init__(self, coefficients):
self.coeff= coefficients
def __call__(self, x):
n = 0
tmp = Prime(0)
for i in self.coeff:
tmp = tmp + (i*(x**n))
n += 1
return tmp
def lagrange(points):
product= functools.reduce(operator.mul, points, 1)
sum= 0
for x in points:
p= 1
for y in points:
if x!= y:
p= p*(x-y)
sum+= poly(x)/(-x*p)
return sum
## Ask the user for a password and gets its hash code with sha256
def password():
p= getpass.getpass()
h= hashlib.sha256(p)
s= h.hexdigest()
constant= int(s, 16)
return constant
## Makes a polynomial with random coefficients and a fixed constant value, and
# evaluates it with n random values an writes the results to a file.
# #param constant The constant value of the polynomial.
# #param evaluations The number of evaluations to be made.
# #param degree The degree of the polynomial.
# #param out_fileName The name of the file where the evaluations are going
# to be written.
# \pre The constant, evaluations and degree must be positive integers.
# \post If no error occurs then, the file whose name was passed will contain
# n evaluations of the polynomial.
def makeKeys(constant, evaluations, degree, out_fileName):
coeffs= []
coeffs.append(Prime(constant))
for x in range(1, degree):
randomc= random.randint(1, p - 1)
coeffs.append(Prime(randomc))
poly= Polynomial(coeffs)
file= open(out_fileName, "w")
for x in range(1, evaluations + 1):
randomi= random.randint(1, p - 1)
points.append(randomi)
e= poly(Prime(randomi))
file.write("(%d, %d)\n" % (randomi, e.n))
file.close()
def encrypt(key, in_fileName, out_fileName):
iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
encryptor = AES.new(key, AES.MODE_ECB, iv)
filesize = os.path.getsize(in_filename)
with open(in_filename, 'rb') as infile:
with open(out_filename, 'wb') as outfile:
outfile.write(struct.pack('<Q', filesize))
outfile.write(iv)
while True:
chunk = infile.read(chunksize)
if len(chunk) == 0:
break
elif len(chunk) % 16 != 0:
chunk += ' ' * (16 - len(chunk) % 16)
outfile.write(encryptor.encrypt(chunk))
def decrypt(ciphertext, key):
iv = ciphertext[:AES.block_size]
cipher = AES.new(key, AES.MODE_ECB, iv)
plaintext = cipher.decrypt(ciphertext[AES.block_size:])
return plaintext.rstrip(b"\0")
def decrypt_file(file_name, key):
with open(file_name, 'rb') as fo:
ciphertext = fo.read()
dec = decrypt(ciphertext, key)
with open(file_name[:-4], 'wb') as fo:
fo.write(dec)
I cannot see the link between pasword and encrypt/decrypt functions but I supose password returns the key. In this case the key is an int that has 32 or 64 bits. Minimum for AES is 128 bits.
Try this:
def password():
p= getpass.getpass()
h= hashlib.sha256(p)
return h.digest()
Here my code:
class typeE:
def __init__(self):
self.u = 0
self.v = 0
self.w = 0
def readData():
global n
global m
global e
e = [typeE]
c = -2
f = open(fi, 'r')
for line in f:
print e[0]
c += 1
ln = [int(i) for i in line.split()]
if c == -1:
n = ln[0]
m = ln[1]
else:
e[c].u = ln[0]
e[c].v = ln[1]
e[c].w = ln[2]
f.close()
Do you have any idea how to make a record like this in Python?
type
typeE = record
u, v, w: longint;
end;
Python is not Pascal. You don't create an "array of records" but a "list of objects" (which can be instances custom class, but in your case could as well be plain dicts).
Also, globals are a bad idea whatever the language, it's always better to use true functions (functions that return a result depending on their input, instead of mutating or rebinding global variables).
The pythonic version of your code (error handling set aside) would look something like this:
class TypeE(object):
def __init__(self, u=0, v=0, w=0):
self.u = u
self.v = v
self.w = w
def __repr__(self):
return "<TypeE({u}, {v}, {w})>".format(**self.__dict__)
def to_int(line):
return [int(i) for i in line.strip().split()]
def read_data(src):
records = []
with open(src, 'r') as f:
headers = to_int(f.next())[:2]
for line in f:
records.append(TypeE(*ln[:3]))
return headers, records
def main():
(m,n), e = read_data("/path/to/your/file")
# now do something with m, n and e
print m, n, e
if __name__ == "__main__":
main()
I'm currently writing a code to perform Gaussian elimination in MATLAB and then write out the code needed to generate a LaTex file showing all the steps. A lot of the times when I do Gaussian elimination the answers start turning into Fractions. So I thought as a nice learning exercise for classes in Matlab that I would write a Fraction class. But I have no clue how to overload operators and frankly Mathwork's documentation wasn't helpful.
classdef Fraction
properties
numer
denom
end
methods
function a = Fraction(numer,denom)
a.denom = denom;
a.numer = numer;
end
function r = mtimes(a,b)
r = Fraction(a.numer*b.numer,a.denom*b.demon);
end
function r = plus(a,b)
c = a.numer*b.denom+a.denom*b.numer;
d = a.denom*b.denom;
r = Fraction(c,d);
function r = minus(a,b)
c = a.numer*b.denom-a.denom*b.numer;
d = a.denom*b.denom;
r = Fraction(c,d);
end
function r = mrdivide(a,b)
r = Fraction(a.numer*b.denom,a.denom*b.numer);
end
function b = reduceFrac(a)
x = a.numer;
y = b.denom;
while y ~= 0
x = y;
y = mod(x,y);
end
b =Fraction(a.numer/x, a.denom/x)
end
end
end
The plus operator works but the other three do not. Does any one have any ideas? Also how do I call my method reduceFrac?
Fraction.reduceFrac(Fraction(2.4))
I thought that the code above would work, but it didn't. Below is the python version of what I am trying to acheive.
Fraction.py
class Fraction(object):
"""Fraction class
Attributes:
numer: the numerator of the fraction.
denom: the denominator of the fraction.
"""
def __init__(self, numer, denom):
"""Initializes the Fraction class
Sets the inital numer and denom for the
fraction class.
Args:
numer: Top number of the Fraction
denom: Bottom number of the Fraction
Returns:
None
Raises:
None
"""
self.numer = numer
self.denom = denom
def __str__(self):
"""function call along with the print command
Args:
None
Returns:
String: numer / denom.
Raises:
None
"""
return str(self.numer) + '/' + str(self.denom)
def get_numer(self):
return self.numer
def set_numer(self, numer):
self.numer = numer
def get_denom(self):
return self.denom
def set_denom(self, denom):
self.denom = denom
def __add__(self, other):
numer = self.numer*other.denom+other.numer*self.denom
denom = self.denom*other.denom
return Fraction.reduceFrac(Fraction(numer,denom))
def __div__(self, other):
numer = self.numer*other.denom
denom = self.denom*other.numer
return Fraction.reduceFrac(Fraction(numer,denom))
def __sub__(self, other):
numer = self.numer*other.denom-other.numer*self.denom
denom = self.denom*other.denom
return Fraction.reduceFrac(Fraction(numer,denom))
def __mul__(self, other):
numer = self.numer*other.numer
denom = self.denom*other.denom
return Fraction.reduceFrac(Fraction(numer,denom))
def reduceFrac(self):
x = self.numer
y = self.denom
while y != 0:
(x, y) = (y, x % y)
return Fraction(self.numer/x, self.denom/x)
if __name__ == "__main__":
v = Fraction(4,3)
g = Fraction(7,8)
r = Fraction(4,8)
a = v + g
print a
s = v - g
print s
d = v / g
print d
m = v * g
print m
f = Fraction.reduceFrac(r)
print f
Your plus function misses an end