-
-
Save lopes/168c9d74b988391e702aac5f4aa69e41 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3 | |
# | |
# This is a simple script to encrypt a message using AES | |
# with CBC mode in Python 3. | |
# Before running it, you must install pycryptodome: | |
# | |
# $ python -m pip install PyCryptodome | |
# | |
# Author.: José Lopes | |
# Date...: 2019-06-14 | |
# License: MIT | |
## | |
from hashlib import md5 | |
from base64 import b64decode | |
from base64 import b64encode | |
from Crypto.Cipher import AES | |
from Crypto.Random import get_random_bytes | |
from Crypto.Util.Padding import pad, unpad | |
class AESCipher: | |
def __init__(self, key): | |
self.key = md5(key.encode('utf8')).digest() | |
def encrypt(self, data): | |
iv = get_random_bytes(AES.block_size) | |
self.cipher = AES.new(self.key, AES.MODE_CBC, iv) | |
return b64encode(iv + self.cipher.encrypt(pad(data.encode('utf-8'), | |
AES.block_size))) | |
def decrypt(self, data): | |
raw = b64decode(data) | |
self.cipher = AES.new(self.key, AES.MODE_CBC, raw[:AES.block_size]) | |
return unpad(self.cipher.decrypt(raw[AES.block_size:]), AES.block_size) | |
if __name__ == '__main__': | |
print('TESTING ENCRYPTION') | |
msg = input('Message...: ') | |
pwd = input('Password..: ') | |
print('Ciphertext:', AESCipher(pwd).encrypt(msg).decode('utf-8')) | |
print('\nTESTING DECRYPTION') | |
cte = input('Ciphertext: ') | |
pwd = input('Password..: ') | |
print('Message...:', AESCipher(pwd).decrypt(cte).decode('utf-8')) |
The class attribute self.cipher
should just be a regular variable (cipher
)
Please help to use 'AES/CBC/PKCS5PADDING' in Python 3
and pycryptodome==3.7.3
String msg = "7977099688";
key = hex("Mu8weQyDvq1HlAzN") XOR hex("PTYfmGYkEJpFem10")
encrypted value should be "UyMO0aehZH/WS+GhjW5Q3A=="
decryption value should be "7977099688"
By using provide algorithm, I am getting:
KEY = '7458791236090c0c2c18690a38180321', PLAINTEXT= '7977099688'
Ciphertext: +s1dIvYm6x4s1Yu0UB2/e5CAZ0n3WjvEVOOPPEr8izs=
I am creating key in below method:
import binascii
static_str = 'Mu8weQyDvq1HlAzN'
st_arr = []
dy_arr = []
for b in bytearray(static_str, "utf-8"):
st_arr.append(b)
token_str = "iNGRmNzJiNGM2NWUxM2I1ZGJmOTk4ZTVhYzUwYzYwYmM5MyIsImp0aSI6IjRjMmFkYmY2LTUxYjEtNGE3My04YjdhLWY1MDZhMmUwNjkzYSIsImlhdCI6MTU3ODQ4ODYyM30.SAjMKd0chcAWoFwMkfxJ-Z1lWRM9-AeSXuHZiXBTYyo"
token_str = token_str[-16:]
for b in bytearray(token_str, "utf-8"):
dy_arr.append(b)
print("Static Bytes= %s \nDynamic Bytes= %s" % (st_arr, dy_arr))
res_byts = []
for bt in bytes(a ^ b for (a, b) in zip(st_arr, dy_arr)):
res_byts.append(bt)
# Converting bytearray to hexadecimal string
key = binascii.hexlify(bytearray(res_byts))
key = key.decode("utf-8")
Help would be appropriated to achieve result. In java it is producing right result. For python I am struggling last two days ...
If you are using Python 3, there is really no need to base64 encode as all strings in python are either bytes or unicode(utf-8)
Example below using:
**
MacOS 10.15.2
Python 3.8
pycryptodome 3.9.4**
- ! I did not test with windows ! -
Problems can occur if you have the older cryptography library installed concurrently with pycryptodome.
Uninstall both and reinstall. Hopefully this helps.
from hashlib import md5
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
class AESCipher:
def __init__(self, key):
password = key.encode('utf-8')
self.key = md5(password).digest()
def encrypt(self, data):
vector = get_random_bytes(AES.block_size)
encryption_cipher = AES.new(self.key, AES.MODE_CBC, vector)
return vector + encryption_cipher.encrypt(pad(data, AES.block_size))
def decrypt(self, data):
file_vector = data[:AES.block_size]
decryption_cipher = AES.new(self.key, AES.MODE_CBC, file_vector)
return unpad(decryption_cipher.decrypt(data[AES.block_size:]), AES.block_size)
if __name__ == '__main__':
print('TESTING ENCRYPTION')
msg = "helloWorld".encode('utf-8')
pwd = "password"
encrypted = AESCipher(pwd).encrypt(msg)
print('Ciphertext:', encrypted)
print('\nTESTING DECRYPTION')
decrypted = AESCipher(pwd).decrypt(encrypted).decode('utf-8')
print("Original data: ", msg.decode('utf-8'))
print("Decripted data:", decrypted)
assert msg.decode('utf-8') == decrypted
Hello Mark,
Thanks for your guide !!
Key should be create as below algorithm:
Secret Key Creation is as follow:
16 Character Static String ("Mu8weQyDvq1HlAzN")
16 Character from end of Token
token_str = "iNGRmNzJiNGM2NWUxM2I1ZGJmOTk4ZTVhYzUwYzYwYmM5MyIsImp0aSI6IjRjMmFkYmY2LTUxYjEtNGE3My04YjdhLWY1MDZhMmUwNjkzYSIsImlhdCI6MTU3ODQ4ODYyM30.SAjMKd0chcAWoFwMkfxJ-Z1lWRM9-AeSXuHZiXBTYyo"
Converting above both string to Hex Code
(hex[Static_String])XOR(hex[Last 16 characters of SSO Token])
Java code working fine for key creation:
public byte[] toHexadecimal(String text) throws UnsupportedEncodingException {
byte[] myBytes = text.getBytes("UTF-8");
return myBytes;
}
public byte[] xorHex(byte[] a, byte[] b) throws UnsupportedEncodingException {
byte[] result = new byte[16];
int i = 0;
for (byte Ab : a) {
result[i] = (byte) (Ab ^ b[i++]);
}
return result;
}
Hex function creation create key as below:
byte[] statickeyHEX = ob.toHexadecimal("Mu8weQyDvq1HlAzN");
byte[] ssoTokenHEX = ob.toHexadecimal(sso);
byte[] secretKey = ob.xorHex(statickeyHEX, ssoTokenHEX);
System.err.println("Secret Key>>>>>>>>>>>>>>"+secretKey);
Output of Secret Key = [B@7852e922
But in Python different. Please guide me to create key
I have found the solution that work perfectly for me:
Code Reference : https://yococoxc.github.io/15493867450071.html
import Crypto.Cipher.AES
import Crypto.Random
import base64
import binascii
class Cipher_AES:
pad_default = lambda x, y: x + (y - len(x) % y) * " ".encode("utf-8")
unpad_default = lambda x: x.rstrip()
pad_user_defined = lambda x, y, z: x + (y - len(x) % y) * z.encode("utf-8")
unpad_user_defined = lambda x, z: x.rstrip(z)
pad_pkcs5 = lambda x, y: x + (y - len(x) % y) * chr(y - len(x) % y).encode("utf-8")
unpad_pkcs5 = lambda x: x[:-ord(x[-1])]
def __init__(self, key="abcdefgh12345678", iv=Crypto.Random.new().read(Crypto.Cipher.AES.block_size)):
self.__key = key
self.__iv = iv
def set_key(self, key):
self.__key = key
def get_key(self):
return self.__key
def set_iv(self, iv):
self.__iv = iv
def get_iv(self):
return self.__iv
def Cipher_MODE_ECB(self):
self.__x = Crypto.Cipher.AES.new(self.__key.encode("utf-8"), Crypto.Cipher.AES.MODE_ECB)
def Cipher_MODE_CBC(self):
self.__x = Crypto.Cipher.AES.new(self.__key.encode("utf-8"), Crypto.Cipher.AES.MODE_CBC,
self.__iv.encode("utf-8"))
def encrypt(self, text, cipher_method, pad_method="", code_method=""):
if cipher_method.upper() == "MODE_ECB":
self.Cipher_MODE_ECB()
elif cipher_method.upper() == "MODE_CBC":
self.Cipher_MODE_CBC()
cipher_text = b"".join([self.__x.encrypt(i) for i in self.text_verify(text.encode("utf-8"), pad_method)])
if code_method.lower() == "base64":
return base64.encodebytes(cipher_text).decode("utf-8").rstrip()
elif code_method.lower() == "hex":
return binascii.b2a_hex(cipher_text).decode("utf-8").rstrip()
else:
return cipher_text.decode("utf-8").rstrip()
def decrypt(self, cipher_text, cipher_method, pad_method="", code_method=""):
if cipher_method.upper() == "MODE_ECB":
self.Cipher_MODE_ECB()
elif cipher_method.upper() == "MODE_CBC":
self.Cipher_MODE_CBC()
if code_method.lower() == "base64":
cipher_text = base64.decodebytes(cipher_text.encode("utf-8"))
elif code_method.lower() == "hex":
cipher_text = binascii.a2b_hex(cipher_text.encode("utf-8"))
else:
cipher_text = cipher_text.encode("utf-8")
return self.unpad_method(self.__x.decrypt(cipher_text).decode("utf-8"), pad_method)
def text_verify(self, text, method):
while len(text) > len(self.__key):
text_slice = text[:len(self.__key)]
text = text[len(self.__key):]
yield text_slice
else:
if len(text) == len(self.__key):
yield text
else:
yield self.pad_method(text, method)
def pad_method(self, text, method):
if method == "":
return Cipher_AES.pad_default(text, len(self.__key))
elif method == "PKCS5Padding":
return Cipher_AES.pad_pkcs5(text, len(self.__key))
else:
return Cipher_AES.pad_user_defined(text, len(self.__key), method)
def unpad_method(self, text, method):
if method == "":
return Cipher_AES.unpad_default(text)
elif method == "PKCS5Padding":
return Cipher_AES.unpad_pkcs5(text)
else:
return Cipher_AES.unpad_user_defined(text, method)
def main2(msg, token):
st_arr = []
dy_arr = []
static_str = 'Mu8weQyDvq1HlAzN'
for b in bytearray(static_str, "utf-8"):
st_arr.append(b)
token_str = token[-16:]
for b in bytearray(token_str, "utf-8"):
dy_arr.append(b)
res_byts = []
for bt in bytes(a ^ b for (a, b) in zip(st_arr, dy_arr)):
res_byts.append(bt)
key = bytes(res_byts).decode()
iv = key
text = msg # "7977099688"
cipher_method = "MODE_CBC"
pad_method = "PKCS5Padding"
code_method = "base64"
cipher_text = Cipher_AES(key, iv).encrypt(text, cipher_method, pad_method, code_method)
cipher_text = cipher_text.replace('\n', '')
print('[' + cipher_text + ']')
print(type(cipher_text))
text = Cipher_AES(key, iv).decrypt(cipher_text, cipher_method, pad_method, code_method)
print(text)
if __name__ == '__main__':
main2("405862999990475",
"CI6MTU3ODQ4ODYyM30.SAjMKd0chcAWoFwMkfxJ-Z1lWRM9-AeSXuHZiXBTYyo")
Code updated. PyCrypto is dead, so I'm using PyCryptodome from now on.