Search code examples
phppythonaesmcryptrijndael

Convert this php encryption function to python


I have been trying to change this php function to python but to no avail.

public static function encode($text, $KEY) {
    $pkcs5text= self::pkcs5_pad($text,16);
    $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($size, MCRYPT_RAND);
    $bin = pack('H*', bin2hex($pkcs5text) );
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $KEY, $bin, MCRYPT_MODE_ECB, $iv);
    return base64_encode($encrypted);
}

My Python script is as below

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

Both scripts generate encoded text from the same message that is different from each other. I am not sure where do I go wrong. How do I implement mcrypt into python on top of rijndael 128?


Solution

  • You have to use the same:

    • block size (Rijndael supports different block sizes and the same has to be used to be compatible)

      BLOCK_SIZE = 16
      
    • padding (PKCS#7 padding pads with bytes that represent the number of padding bytes)

      padbyte = BLOCK_SIZE - len(plaintext) % BLOCK_SIZE
      padded_text = plaintext + padbyte * chr(padbyte)
      

    Security considerations:

    Never use ECB mode. It's very insecure. Use at the very least CBC mode with a random IV. The IV doesn't have to be secret, so you can prepend it to the ciphertext and slice it off before decryption.

    Authenticate your ciphertexts: Use an encrypt-then-MAC scheme to protect from (malicious) modifications of your ciphertexts with a strong MAC such as HMAC-SHA256 or use an authenticated mode like GCM.