2

I am just wondering is it possible to convert PHP encryption function to Python? I am using PHP function to encrypt USER ID and store it in Database and now I need to decrypt USER ID in Python, I using this PHP function:

function decrypt($id) {
       $cryptKey  = '123';
       $decoded    = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, md5( $cryptKey ),         base64_decode( $id ), MCRYPT_MODE_CBC, md5( md5( $cryptKey ) ) ), "\0");
       return( $decoded );
    }
Streem
  • 628
  • 2
  • 12
  • 26
  • Possible duplicate of [Decrypting strings in Python that were encrypted with MCRYPT\_RIJNDAEL\_256 in PHP](http://stackoverflow.com/questions/8217269/decrypting-strings-in-python-that-were-encrypted-with-mcrypt-rijndael-256-in-php) – Arya McCarthy May 06 '17 at 08:09

1 Answers1

7

Here is your function 'translated' to python

from Crypto.Cipher import AES
from hashlib import md5

def decrypt(id): 
    cryptKey  = '123'
    cipher = AES.new(key=md5(cryptKey).hexdigest(), mode=AES.MODE_CBC, IV=md5(md5(cryptKey).hexdigest()).hexdigest()[:16])
    decoded = cipher.decrypt(id.decode('base64')).rstrip('\0')
    return decoded

A fiew suggestions
1. Use a random iv
2. Use a more complex key
3. Don't hardcode the key
4. Use openssl_decrypt , mcrypt_decrypt is deprecated

Note
This will not work with MCRYPT_RIJNDAEL_256 because it uses 32 byte blocks .
But you could use MCRYPT_RIJNDAEL_128 or openssl

Here is an example with openssl AES CBC in PHP :

function encrypt($data, $key) {
    $method = "aes-" . strlen($key) * 8 . "-cbc";
    $iv = openssl_random_pseudo_bytes(16);
    $encoded = base64_encode($iv . openssl_encrypt($data, $method, $key, TRUE, $iv));
    return $encoded;
}

function decrypt($data, $key) {
    $method = "aes-" . strlen($key) * 8 . "-cbc";
    $iv = substr(base64_decode($data), 0, 16);
    $decoded = openssl_decrypt(substr(base64_decode($data), 16), $method, $key, TRUE, $iv);
    return $decoded;
}

Python code :

from Crypto.Cipher import AES
from Crypto import Random
import base64

def encrypt(data, key): 
    pkcs7pad = lambda data: data + chr(16-(len(data)%16)).encode() * (16-(len(data)%16))
    iv = Random.new().read(16)
    cipher = AES.new(key=key, mode=AES.MODE_CBC, IV=iv)
    encoded = base64.b64encode(iv + cipher.encrypt(pkcs7pad(data)))
    return encoded

def decrypt(data, key): 
    pkcs7unpad = lambda data: data[:-ord(data[-1:])]
    cipher = AES.new(key=key, mode=AES.MODE_CBC, IV=base64.b64decode(data)[:16])
    decoded = cipher.decrypt(base64.b64decode(data)[16:])
    return pkcs7unpad(decoded)

With the above functions you can encrypt in PHP - decrypt in python , and vice versa
Assuming that the key has a valid size (16, 24 or 32 bytes)

t.m.adam
  • 15,106
  • 3
  • 32
  • 52
  • Thanks, you have saved my day!:) – Streem May 06 '17 at 08:48
  • Yes, I have tried it I am receiving error: "binascii.Error: Incorrect padding" my encoded PHP id: "VjceE1sAhxf2kUJYJX5q1BruIco2ne9SBAjzmbgjfno%3D" as I understand something is not right with my encoded ID string I am looking for a solution right now – user2808421 May 06 '17 at 09:08
  • I receive same error:/ could it be there is a mistake in decode function? – Streem May 06 '17 at 09:12
  • Error: 'output = base64.decodestring(input) File "/usr/local/lib/python2.7/base64.py", line 328, in decodestring return binascii.a2b_base64(s) binascii.Error: Incorrect padding' – Streem May 06 '17 at 09:13
  • I could make it work with `RIJNDAEL 128` and `openssl_decrypt` ( 128 and 256 ) , but not with `RIJNDAEL 256` – t.m.adam May 06 '17 at 09:20
  • Very clear and detailed answer, thank you very much!:) – Streem May 06 '17 at 11:28