Skip to content

Instantly share code, notes, and snippets.

@jchysk
Created May 10, 2016 05:03
Show Gist options
  • Save jchysk/8c2f44e45f5c9a28c824d03de7aee46e to your computer and use it in GitHub Desktop.
Save jchysk/8c2f44e45f5c9a28c824d03de7aee46e to your computer and use it in GitHub Desktop.
A number of helper functions for common cryptography uses
"""
from helpers import generate_RSA, encrypt_RSA, generate_password, decrypt_RSA, generate_AES, decrypt_AES, pad
priv, pub = generate_RSA()
encrypted = encrypt_RSA(pub, generate_password())
key, iv, encryptor = generate_AES()
aes_encrypted = encryptor.encrypt(pad("this is a very long string " * 25))
decrypt_AES(key, iv, aes_encrypted)
"""
BS = 16
# This padding follows the PKCS#5 standard of padding regardless of current length
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s: s[0:-ord(s[-1])] if len(s) > 0 and ord(s[-1]) <= 16 else s
def generate_number(digits):
import random
import string
rng = random.SystemRandom()
vc = string.digits
h1 = ''.join([rng.choice(vc) for i in range(digits)])
return h1
def generate_password(length=32):
"""Generates a password"""
import random
import string
rng = random.SystemRandom()
vc = string.ascii_letters + string.digits
return ''.join([rng.choice(vc) for i in range(length)])
def decrypt_AES(cipher, iv, package):
from Crypto.Cipher import AES
cipher_obj = AES.new(cipher, AES.MODE_CBC, iv)
return cipher_obj.decrypt(package)
def generate_AES(key=None, iv=None):
'''
Generates an AES key and encryptor object that can encrypt text using the key
:param key: Can manually specify the AES key to be used, or let it be generated
:param iv: Can manually specify the IV, or let it be generated
'''
from Crypto.Cipher import AES
if key is None:
key = generate_password()
if iv is None:
iv = generate_password(16)
encryptor = AES.new(key, AES.MODE_CBC, iv)
return key, iv, encryptor
def decrypt_RSA(key, package):
'''
Decrypt RSA encrypted package with private key
:param key: Private key
:param package: Base64 encoded string to decrypt
:return: String decrypted
'''
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from base64 import b64decode
rsakey = RSA.importKey(key)
# SHA1 and MGF1
rsakey = PKCS1_OAEP.new(rsakey)
decrypted = rsakey.decrypt(b64decode(package))
return decrypted
def encrypt_RSA(key, message):
'''
RSA encrypts the message using the public key
:param key: Public key to encrypt with
:param message: String to be encrypted
:return: Base64 encoded encrypted string
'''
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
rsakey = RSA.importKey(key)
# SHA1 and MGF1
rsakey = PKCS1_OAEP.new(rsakey)
encrypted = rsakey.encrypt(message)
return encrypted.encode('base64')
def generate_RSA(bits=2048):
"""
Generate an RSA keypair with exponent of 65537 in PEM format
:param bits The key length in bits
:return private key and public key
"""
from Crypto.PublicKey import RSA
new_key = RSA.generate(bits, e=65537)
public_key = new_key.publickey().exportKey("PEM")
private_key = new_key.exportKey("PEM")
return private_key.strip(), public_key.strip()
def verify_sign(pub_key, signature, data):
'''
Verifies with a public key from whom the data came that it was indeed
signed by their private key.
:param pub_key: Public key
:param signature: String signature to be verified
:param data: The data the signature was created with
:return: Boolean. True for verified. False for not verified.
'''
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64decode
verified = False
try:
'''Needs to be in try because signer verify will sometimes run
Value exception on improper signature strings instead of just
returning false'''
rsakey = RSA.importKey(pub_key)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
digest.update(b64decode(data))
if signer.verify(digest, b64decode(signature)):
verified = True
finally:
return verified
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment