Skip to content

Instantly share code, notes, and snippets.

@LuoZijun
Last active January 12, 2021 05:14
Show Gist options
  • Save LuoZijun/80e138446f26eb892a16 to your computer and use it in GitHub Desktop.
Save LuoZijun/80e138446f26eb892a16 to your computer and use it in GitHub Desktop.
Python AES
#!/usr/bin/env python
#coding: utf8
import base64
import hashlib
import binascii
from Crypto import Random
from Crypto.Cipher import AES
from os import urandom
import os
BS = 32
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[:-ord(s[len(s)-1:])]
import math
import random
"""
AES: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
JavaScript: https://github.com/mdp/gibberish-aes
Python: https://stackoverflow.com/questions/12221484/how-come-i-cant-decrypted-my-aes-encrypted-message-on-someone-elses-aes-decrypt
https://stackoverflow.com/questions/13907841/implement-openssl-aes-encryption-in-python
https://stackoverflow.com/questions/16761458/how-to-aes-encrypt-decrypt-files-using-python-pycrypto-in-an-openssl-compatible
"""
def randArr ( num ):
"""
JavaScript Code:
var result = [], i;
for (i = 0; i < num; i++) {
result = result.concat(Math.floor(Math.random() * 256));
}
return result;
"""
return map( lambda i: math.floor(random.random() * 256 ), xrange(num) )
def s2a(s, binary):
"""
JavaScript Code:
var array = [], i;
if (! binary) {
string = enc_utf8(string);
}
for (i = 0; i < string.length; i++) {
array[i] = string.charCodeAt(i);
}
return array;
"""
return map( lambda s: ord(s), list(s) )
def openSSLKey(passwordArr, saltArr, Nr, Nk):
# Nr: Default to 256 Bit Encryption
# // Number of rounds depends on the size of the AES in use
# // 3 rounds for 256
# // 2 rounds for the key, 1 for the IV
# // 2 rounds for 128
# // 1 round for the key, 1 round for the IV
# // 3 rounds for 192 since it's not evenly divided by 128 bits
# if !Nr: Nr = 14
# if !Nk: Nk = 8
# if Nr >= 12: rounds = 3
# else: rounds = 2
# key = []
# iv = []
# md5_hash = []
# result = []
# data00 = passwordArr + saltArr
"""
JavaScript Code:
var rounds = Nr >= 12 ? 3: 2,
key = [],
iv = [],
md5_hash = [],
result = [],
data00 = passwordArr.concat(saltArr),
i;
md5_hash[0] = MD5(data00);
result = md5_hash[0];
for (i = 1; i < rounds; i++) {
md5_hash[i] = MD5(md5_hash[i - 1].concat(data00));
result = result.concat(md5_hash[i]);
}
key = result.slice(0, 4 * Nk);
iv = result.slice(4 * Nk, 4 * Nk + 16);
return {
key: key,
iv: iv
};
"""
pass
class AESCipher2:
def __init__( self, key ):
self.key = hashlib.sha256(key).digest()
def encrypt( self, raw ):
raw = pad(raw)
iv = Random.new().read( AES.block_size )
cipher = AES.new( self.key, AES.MODE_CBC, iv )
return base64.b64encode( iv + cipher.encrypt( raw ) )
def decrypt( self, enc ):
enc = base64.b64decode(enc)
iv = enc[:16]
cipher = AES.new(self.key, AES.MODE_CBC, iv )
return unpad(cipher.decrypt( enc[16:] ))
def derive_key_and_iv(password, salt, key_length, iv_length):
d = d_i = ''
while len(d) < key_length + iv_length:
d_i = hashlib.md5(d_i + password + salt).digest()
d += d_i
return d[:key_length], d[key_length:key_length+iv_length]
class AESCipher:
def __init__(self):
pass
def encrypt(self, plaintext, password, key_length=32):
data = ""
bs = AES.block_size
salt = Random.new().read(bs - len('Salted__'))
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
data += 'Salted__' + salt
chunk = plaintext
if len(chunk) == 0 or len(chunk) % bs != 0:
padding_length = (bs - len(chunk) % bs) or bs
chunk += padding_length * chr(padding_length)
data += cipher.encrypt( chunk )
return base64.b64encode(data)
def decrypt(self, data, password, key_length=32):
data = base64.b64decode(data)
bs = AES.block_size
salt = data[len("Salted__"): 16]
data = data[len("Salted__")+len(salt): ]
key, iv = derive_key_and_iv(password, salt, key_length, bs)
cipher = AES.new(key, AES.MODE_CBC, iv)
chunk = cipher.decrypt( data )
padding_length = ord(chunk[-1])
return chunk[:-padding_length]
OpenSSL_AES = AESCipher()
KEY = "imtest"
def encrypt(plaintext, key="imtest"):
return OpenSSL_AES.encrypt(plaintext, key)
def decrypt(data, key="imtest"):
return OpenSSL_AES.decrypt(plaintext, key)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment