Reputation: 1608
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?
Upvotes: 0
Views: 824
Reputation: 61952
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.
Upvotes: 1
Reputation: 6357
Given your initialization vector is being randomly created in the first example, it's no surprise that the output looks different encrypted and Base 64 encoded. What's important is that you can decode and dycrypt reliably.
Also, your python code doesn't look like it's using an initialization vector at all (unless the libraries do it by default, which in this case, they're not). This means you won't be using cypher block chaining and thus less secure than the PHP example.
The first few bytes of your unencoded output are traditionally the initialization vector, which the receiver knows the length of and then uses to initialize the decryption process.
It looks like the Python 2.x libraries aren't particularly useful, see this example here. Python 3 seems to have what you require here.
Also, for block size, use 16 as it's the AES standard (see here), 32 won't work.
Upvotes: 1