Correctly migrate from Python 2 md5 library to Python 3 hashlib
Question:
I’m trying to integrate a 3rd party payment gateway (CCAvenue
) in Django 1.11, Python 3.5.2
The reference code provided by the 3rd party uses the deprecated library md5 to encrypt texts.
from Crypto.Cipher import AES
import md5
def pad(data):
length = 16 - (len(data) % 16)
data += chr(length)*length
return data
def encrypt(plainText,workingKey):
iv = 'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
plainText = pad(plainText)
encDigest = md5.new ()
encDigest.update(workingKey)
enc_cipher = AES.new(encDigest.digest(), AES.MODE_CBC, iv)
encryptedText = enc_cipher.encrypt(plainText).encode('hex')
return encryptedText
How do I make the above encrypt()
method Python 3 compatible using the hashlib
library of Python 3? Can you post the whole method?
Answers:
WARNING: Don’t use crypto or pycrypto anymore! read more
Here’s a Python 3 compatible way of doing the same:
from binascii import hexlify, unhexlify
from Crypto.Cipher import AES
from hashlib import md5
from django.utils.encoding import force_bytes
iv = 'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
# for python 3.9 & pycryptodome, this need to be byte
iv = b'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
BS = 16
def _pad(data):
return data + (BS - len(data) % BS) * chr(BS - len(data) % BS)
def _unpad(data):
return data[0:-ord(data[-1])]
def encrypt(plain_text, working_key):
plain_text = _pad(plain_text)
enc_cipher = AES.new(md5(force_bytes(working_key)).digest(), AES.MODE_CBC, _iv)
return hexlify(enc_cipher.encrypt(plain_text)).decode('utf-8')
def decrypt(cipher_text, working_key):
encrypted_text = unhexlify(cipher_text)
dec_cipher = AES.new(md5(force_bytes(working_key)).digest(), AES.MODE_CBC, _iv)
return _unpad(dec_cipher.decrypt(encrypted_text).decode('utf-8'))
Works perfectly for python3.8 and Django 3.2 pycryptodome==3.17
from Crypto.Cipher import AES
import hashlib
from binascii import hexlify, unhexlify
def pad(data):
length = 16 - (len(data) % 16)
data += chr(length)*length
return data
def unpad(data):
return data[0:-ord(data[-1])]
def encrypt(plainText, workingKey):
iv =b'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
plainText = pad(plainText)
bytearrayWorkingKey = bytearray()
bytearrayWorkingKey.extend(map(ord, workingKey))
enc_cipher = AES.new(hashlib.md5(bytearrayWorkingKey).digest(), AES.MODE_CBC, iv)
return hexlify(enc_cipher.encrypt(plainText.encode('utf-8'))).decode('utf-8')
def decrypt(cipherText, workingKey):
iv = b'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
encryptedText = unhexlify(cipherText)
bytearrayWorkingKey = bytearray()
bytearrayWorkingKey.extend(map(ord, workingKey))
decCipher = AES.new(hashlib.md5(bytearrayWorkingKey).digest(), AES.MODE_CBC, iv)
return unpad(decCipher.decrypt(encryptedText).decode('utf-8'))`
I’m trying to integrate a 3rd party payment gateway (CCAvenue
) in Django 1.11, Python 3.5.2
The reference code provided by the 3rd party uses the deprecated library md5 to encrypt texts.
from Crypto.Cipher import AES
import md5
def pad(data):
length = 16 - (len(data) % 16)
data += chr(length)*length
return data
def encrypt(plainText,workingKey):
iv = 'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
plainText = pad(plainText)
encDigest = md5.new ()
encDigest.update(workingKey)
enc_cipher = AES.new(encDigest.digest(), AES.MODE_CBC, iv)
encryptedText = enc_cipher.encrypt(plainText).encode('hex')
return encryptedText
How do I make the above encrypt()
method Python 3 compatible using the hashlib
library of Python 3? Can you post the whole method?
WARNING: Don’t use crypto or pycrypto anymore! read more
Here’s a Python 3 compatible way of doing the same:
from binascii import hexlify, unhexlify
from Crypto.Cipher import AES
from hashlib import md5
from django.utils.encoding import force_bytes
iv = 'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
# for python 3.9 & pycryptodome, this need to be byte
iv = b'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
BS = 16
def _pad(data):
return data + (BS - len(data) % BS) * chr(BS - len(data) % BS)
def _unpad(data):
return data[0:-ord(data[-1])]
def encrypt(plain_text, working_key):
plain_text = _pad(plain_text)
enc_cipher = AES.new(md5(force_bytes(working_key)).digest(), AES.MODE_CBC, _iv)
return hexlify(enc_cipher.encrypt(plain_text)).decode('utf-8')
def decrypt(cipher_text, working_key):
encrypted_text = unhexlify(cipher_text)
dec_cipher = AES.new(md5(force_bytes(working_key)).digest(), AES.MODE_CBC, _iv)
return _unpad(dec_cipher.decrypt(encrypted_text).decode('utf-8'))
Works perfectly for python3.8 and Django 3.2 pycryptodome==3.17
from Crypto.Cipher import AES
import hashlib
from binascii import hexlify, unhexlify
def pad(data):
length = 16 - (len(data) % 16)
data += chr(length)*length
return data
def unpad(data):
return data[0:-ord(data[-1])]
def encrypt(plainText, workingKey):
iv =b'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
plainText = pad(plainText)
bytearrayWorkingKey = bytearray()
bytearrayWorkingKey.extend(map(ord, workingKey))
enc_cipher = AES.new(hashlib.md5(bytearrayWorkingKey).digest(), AES.MODE_CBC, iv)
return hexlify(enc_cipher.encrypt(plainText.encode('utf-8'))).decode('utf-8')
def decrypt(cipherText, workingKey):
iv = b'x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f'
encryptedText = unhexlify(cipherText)
bytearrayWorkingKey = bytearray()
bytearrayWorkingKey.extend(map(ord, workingKey))
decCipher = AES.new(hashlib.md5(bytearrayWorkingKey).digest(), AES.MODE_CBC, iv)
return unpad(decCipher.decrypt(encryptedText).decode('utf-8'))`