cryptography – Generate public / private keys, encrypt, decrypt, sign, verify, in Python. A bit fast

My program generates public private keys, encodes, decrypts, signs and verifies, while using AES for bulk speed. Many operations were chosen for speed. This works out of the box at 3.6+. Windows idle env does not allow you to work there, but Linux and Mac are ideal. I call gzip, which I know I can replace with a module. I almost want to do my own huffman coding for that, but I do not know where to draw the line.

The RSA and DSA parts are written from number theory and do not use the modules, that was the point.

I am using this as an educational tool that forces those who are not willing to kinetically understand public and private key cryptography when it is transmitted on a USB device, etc., in a classroom. To see the clicks in people's eyes when they understand the signature or something similar, that's why I share this code. I know there are much better ways to handle data concatenation, but I'm glad you're processing the data at the binary level.

I love the prime number theorem and you should too. 🙂

#! / usr / bin / env python3
import os
import systems
import mathematics
import re
import hashlib
import randomly
import base64
import chain
getpass import
import multiprocessing as mp
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Protocol.KDF import PBKDF2

# Crime tests, maximum common common divisor and least common multiple
def isprime (n):
if it is not n & 1: #check if the first bit is 1
false return
for i in (3,5,7,11):
if divmod (n, i)[1] == 0:
false return
#Fermato
if (pow (2, n-1, n))! = 1:
false return
#MilRab, x ** 2 = 1 mod P - ERH
s = 0
d = n-1
while not d & 1:
d >> = 1 # change the binary representation of the number in one place, same as divide by 2 ^ d
s + = 1
assert (2 ** s * d == n-1) #Process to find s and d
def trial_composite (a):
if pow (a, d, n) == 1:
false return
for i in rank (s):
if pow (a, 2 ** i * d, n) == n-1:
false return
return true
for i in the range (100): # Number of Rabin witnesses
a = random.randrange (2, n-1)
if trial_composite (a):
false return
return true

def get1prime (key size):
while True
p = random.randrange (1 << (key size), 1 <<(keysize+2))
       if isprime(p):
           return p

def modInverse(a, m) : #Euclid's Extended Algorithm
   m0 = m
   y = 0
   x = 1
   while (a > one):
q = a // m
t = m
m = divmod (a, m)[1]
       a = t
t = y
y = x - q * y
x = t
yes (x < 0) :
       x = x + m0
   return x

def lcm(x, y):
  lcm = (x*y)//math.gcd(x,y)
  return lcm

##AES256CHUNK
def get_private_key(password):
   salt = b"We will know, we must know"
   kdf = PBKDF2(password, salt, 64, 1000)
   key = kdf[:32]
   return key

def encryptaes(raw, password):
   private_key = password
   raw = pad(raw)
   iv = Random.new().read(AES.block_size)
   cipher = AES.new(private_key, AES.MODE_CBC, iv)
   return base64.b64encode(iv + cipher.encrypt(raw))

def decryptaes(enc, password):
   private_key = password
   enc = base64.b64decode(enc)
   iv = enc[:16]
   cipher = AES.new(private_key, AES.MODE_CBC, iv)
   return unpad(cipher.decrypt(enc[16:]))

BLOCK_SIZE = 128 #Block is 128 no matter what,this is multiple of 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

#RSA
#Unique and Arbitrary Pub E, a prime.
e = 66047 # because I can
#e = 65537

def encryptit(e, n, thestring):#for sigining pass d as e
   rbinlist = ['{0:08b}'.format(x) for x in thestring] 
   catstring = ''
   catstring += rbinlist[0].lstrip('0')
   del rbinlist[0]
   for i in rbinlist:
       catstring += str(i)
   puttynumber = int(catstring,2)
   cypherstring = str(pow(puttynumber, e, n))
   return cypherstring

def decryptit(d, n, cynum):#for signing pass e as d
   decryptmsg = ''
   n = int(n)
   d = int(d)
   puttynum = pow(int(cynum), d, n)
   puttynum = '{0:08b}'.format(puttynum)
   while True:
       if len(puttynum)%8 == 0:
           break
       puttynum = '0{0}'.format(puttynum)
   locs = re.findall('[01]{8}', puttynum)
   for x in locs:
       letter = chr(int(x,2))
       decryptmsg += letter
   return decryptmsg

#Begin User Flow
choice = input("""



Welcome to Dan's Cryptography Concept Program. 
Generate/Encrypt/Decrypt/Sign
RSA++/DSA++/AES/OTP/Double DH key exch w SHA
Choose:
A: Generate New Public/Private Key Pair
B: Encrypt a File
C: Decrypt a File
=> "" ")

If the option == & # 39; A & # 39; or the option == & # 39; a & # 39;
try:
keysize = (int (input ("Enter a keysize:")) >> 1)
except ValueError as:
print (& # 39; Enter a number  n  n & # 39;)
sys.exit ()
pubkeyname = input (& # 39; Enter the desired public key name: & # 39;)
pkey = input (& # 39; Enter the desired private key name: & # 39;)
pwkey = get_private_key (getpass.getpass (prompt = & # 39; Password to protect your private key: & # 39 ;, stream = None))
print (& # 39; Generating keys ... & # 39;)
cousins ​​= []
   plist = []
   for i in the range (mp.cpu_count ()):
plist.append (key size)
Workgroup = mp.Pool (processes = mp.cpu_count ())
reslist = workpool.imap_unordered (get1prime, plist)
workpool.close ()
for res in reslist:
if res:
primes.append (res)
workpool.terminate ()
break
workpool.join ()
#
workpool1 = mp.Pool (processes = mp.cpu_count ())
reslist = workpool1.imap_unordered (get1prime, plist)
workpool1.close ()
for res in reslist:
if res:
primes.append (res)
workpool1.terminate ()
break
workpool1.join ()
yes cousins[0] ! = prime numbers[1]:
p, q = prime numbers[0]cousins[1]
   plus:
Print (& Try again unlucky & # 39;)
exit()
n = p * q
cm = mcm (p-1, q-1)
print (& # 39; Computing Private key ... & # 39;)
d = modInverse (e, cm)
print (& # 39; Private key size: {} bits & # 39;. format (key size * 2))
print (& # 39; Functional length of: format {} & # 39 ;. (len (bin ((d)))))
keystring = encryptaes (str (d) .encode (& # 39; ascii & # 39 ;, errors = & # 39; ignore & # 39;). decode (& # 39; utf-8 & # 39;), pwkey)
b64key = bytes.decode (base64.encodestring (bytes (str (hex (n)). encode ())))
with open (pkey, & # 39; w & # 39;) as f1:
f1.write (str (n) + & # 39;  n & # 39;)
f1.write (bytes.decode (string of keys))
with open (pubkeyname, & # 39; w & # 39;) as f2:
f2.write (b64key)
print (& # 39; Complete - {} and {} generated & # 39; .format (pub key name, pkey))
print (& # 39; e exponent: {} & # 39 ;. format (str (e)))
Print("""
----- THE PUBLIC KEY BEGINS -----
{} ----- FINAL PUBLIC KEY -----
"" ".format (b64key))
b64privkey = b64key = bytes.decode (base64.encodestring (bytes (str (hex (d)). encode ())))
Print("""
----- THE PRIVATE KEY BEGINS -----
{} ----- FINAL PRIVATE KEY -----
"" ".format (b64privkey))

If the option == & # 39; B & # 39; or the option == & # 39; b & # 39;
lineoutholder = []
   pubkeyname = input (& # 39; Enter the PUBLIC key to encrypt with (receiver): & # 39;)
privkey = input (& # 39; Enter your private key with the one you want to sign (yours): & # 39;)
pwkey = get_private_key (getpass.getpass (prompt = & # 39; Password for your private key: & # 39 ;, stream = None))
try:
with open (pubkeyname, & # 39; r & # 39;) as f1:
pubkey = f1.read ()
except:
print (& # 39; bad keyname & # 39;)
exit()
uhaeskey = & # 39; & # 39; .join ([random.choice(string.ascii_letters + string.digits) for n in range(32)])
n = int (bytes.decode (base64.decodestring (bytes (pubkey.encode ()))), 16)
workfile = input (& # 39; Enter the file for ENCRYPT: & # 39;)
outfile = input (& # 39; Enter filename to WRITE: & # 39;)
sha256_hash = hashlib.sha256 ()
try:
with open (work file, & # 39; rb & # 39;) as f2:
wholefile = f2.read ()
with open (work file, & # 39; rb & # 39;) as f2: # open again to clear the memory
for byte_block in iter (lambda: f2.read (4096), b ""):
sha256_hash.update (byte_block)
HASH = sha256_hash.hexdigest ()
with open (privkey) as f3:
priv = f3.readlines ()
except exception as x:
print (x)
exit()
d = int (bytes.decode (decryptaes (priv[1], pwkey)))
HASH = [ord(i) for i in HASH]
   numhash = & # 39; & # 39;
for i in HASH:
numhash + = str (i)
signature = pow (int (numhash), d, int (priv[0]))
aeskey = get_private_key (uhaeskey)
plaintext = base64.encodestring (wholefile)
cyphertext = bytes.decode (encryptaes (plaintext.decode (& # 39; ascii & # 39;), aeskey))
embarpw = encryptit (e, n, uhaeskey.encode ())
concat = str (str (signature) + & # 39; CUTcutCUTcutCUT & # 39; + shippw + & # CUTcutCUTcutCUT & # 39; + cyphertext)
with open (outfile, & # 39; w & # 39;) as f3:
f3.write (concat)
os.system (& # 39; gzip -9 {0}; mv {0} .gz {0} & # 39;. format (outfile))
print (& # 39; It was written in {} ... & # 39; format (outfile))

If the option == & # 39; C & # 39; or the option == & # 39; c & # 39;
dspubkeyname = input (& # 39; Enter the PUBLIC key to verify the signature with (sender): & # 39;)
try:
with open (dspubkeyname, & # 39; r & # 39;) as f1:
pubkey = f1.read ()
except:
print (& # 39; bad keyname & # 39;)
exit()
nsig = int (bytes.decode (base64.decodestring (bytes (pubkey.encode ())), 16)
privkey = input (& # 39; YOUR private KEY file name to decrypt the data: & # 39;)
pwkey = get_private_key (getpass.getpass (prompt = & # 39; Password for your private key file: & # 39 ;, flow = None))
workfile = input (& # 39; Enter the file to DECRYPT: & # 39;)
outfile = input (& # 39; Enter the file name to WRITE: & # 39;)
print (& # 39; DECRYPTING & # 39;)
os.system (& # 39; mv {0} {0} .gz; gzip -d {0} .gz & # 39; .format (work file))
sha256_hash = hashlib.sha256 ()
try:
with open (workfile) as f1:
lineholder = f1.read (). split (& # 39; CUTcutCUTcutCUT & # 39;)
signature, codedkey, cyphertext = lineholder[0]line holder[1]line holder[2]
   except:
print (& # 39; File name or path & # 39;)
exit()
try:
with open (privkey) as f2:
priv = f2.readlines ()
except:
print (& # 39; Location of wrong private key & # 39;)
n = priv[0]
   d = int (bytes.decode (decryptaes (priv[1], pwkey)))
sigdec = pow (int (signature), e, nsig) #Sig Verification step1
aeskey = decipher (d, n, codedkey)
aeskey = get_private_key (aeskey)
decstr = bytes.decode (decryptaes (cyphertext, aeskey))
cleartext = base64.decodestring (bytes (decstr, & # 39; ascii & # 39;))
with open (outfile, & # 39; wb & # 39;) as f1:
f1.write (clear text)
with open (outfile, & # 39; rb & # 39;) as f2:
for byte_block in iter (lambda: f2.read (4096), b ""):
sha256_hash.update (byte_block)
HASH = sha256_hash.hexdigest ()
HASH = [ord(i) for i in HASH]
   numhash = & # 39; & # 39;
for i in HASH:
numhash + = str (i)
if int (numhash) == int (sigdec):
print (& # 39; verified signature & # 39;)
plus:
print (& # 39; FAILURE, bad hash ... & # 39;)
print (& # 39; wrote in {} & # 39; .format (outfile))