Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decrypting strings in Python that were encrypted with MCRYPT_RIJNDAEL_256 in PHP

I have a function in PHP that encrypts text as follows:

function encrypt($text)
{
    $Key = "MyKey";

    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $Key, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));
}

How do I decrypt these values in Python?

like image 224
dharmesh Avatar asked Nov 21 '11 19:11

dharmesh


People also ask

How do you encrypt and decrypt a PHP string?

In PHP, Encryption and Decryption of a string is possible using one of the Cryptography Extensions called OpenSSL function for encrypt and decrypt. openssl_encrypt() Function: The openssl_encrypt() function is used to encrypt the data. Parameters: $data: It holds the string or data which need to be encrypted.

Which encryption is used in PHP?

Secret Key Encryption is also called Symmetric encryption, The Secret Key Encryption of the PHP uses just one key, called a shared secret, for both encrypting and decrypting. To encrypt the data, Here one same key is used by the sender (for encryption) and the receiver (for decryption).


1 Answers

To decrypt this form of encryption, you will need to get a version of Rijndael. One can be found here. Then you will need to simulate the key and text padding used in the PHP Mcrypt module. They add '\0' to pad out the text and key to the correct size. They are using a 256 bit block size and the key size used with the key you give is 128 (it may increase if you give it a bigger key). Unfortunately, the Python implementation I've linked to only encodes a single block at a time. I've created python functions which simulate the encryption (for testing) and decryption in Python

import rijndael
import base64

KEY_SIZE = 16
BLOCK_SIZE = 32

def encrypt(key, plaintext):
    padded_key = key.ljust(KEY_SIZE, '\0')
    padded_text = plaintext + (BLOCK_SIZE - len(plaintext) % BLOCK_SIZE) * '\0'

    # could also be one of
    #if len(plaintext) % BLOCK_SIZE != 0:
    #    padded_text = plaintext.ljust((len(plaintext) / BLOCK_SIZE) + 1 * BLOCKSIZE), '\0')
    # -OR-
    #padded_text = plaintext.ljust((len(plaintext) + (BLOCK_SIZE - len(plaintext) % BLOCK_SIZE)), '\0')

    r = rijndael.rijndael(padded_key, BLOCK_SIZE)

    ciphertext = ''
    for start in range(0, len(padded_text), BLOCK_SIZE):
        ciphertext += r.encrypt(padded_text[start:start+BLOCK_SIZE])

    encoded = base64.b64encode(ciphertext)

    return encoded


def decrypt(key, encoded):
    padded_key = key.ljust(KEY_SIZE, '\0')

    ciphertext = base64.b64decode(encoded)

    r = rijndael.rijndael(padded_key, BLOCK_SIZE)

    padded_text = ''
    for start in range(0, len(ciphertext), BLOCK_SIZE):
        padded_text += r.decrypt(ciphertext[start:start+BLOCK_SIZE])

    plaintext = padded_text.split('\x00', 1)[0]

    return plaintext

This can be used as follows:

key = 'MyKey'
text = 'test'

encoded = encrypt(key, text)
print repr(encoded)
# prints 'I+KlvwIK2e690lPLDQMMUf5kfZmdZRIexYJp1SLWRJY='

decoded = decrypt(key, encoded)
print repr(decoded)
# prints 'test'

For comparison, here is the output from PHP with the same text:

$ php -a
Interactive shell

php > $key = 'MyKey';
php > $text = 'test';
php > $output = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB);
php > $encoded = base64_encode($output);
php > echo $encoded;
I+KlvwIK2e690lPLDQMMUf5kfZmdZRIexYJp1SLWRJY=
like image 137
101100 Avatar answered Oct 05 '22 14:10

101100