Расшифровка строк в Python, которые были зашифрованы с помощью MCRYPT_RIJNDAEL_256 в PHP

У меня есть функция в PHP, которая шифрует текст следующим образом:

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)))); } 

Как расшифровать эти значения в Python?

Чтобы расшифровать эту форму шифрования, вам нужно будет получить версию Rijndael. Здесь можно найти. Затем вам нужно будет имитировать ключ и текстовое дополнение, используемое в модуле PHP Mcrypt. Они добавляют '\0' чтобы выровнять текст и ввести правильный размер. Они используют 256-битный размер блока, а размер ключа, используемый с ключом, который вы даете, составляет 128 (это может увеличиться, если вы дадите ему более крупный ключ). К сожалению, реализация Python, с которой я связан, кодирует только один блок за раз. Я создал функции python, которые имитируют шифрование (для тестирования) и дешифрование в 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 

Это можно использовать следующим образом:

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

Для сравнения, вот вывод PHP с тем же текстом:

 $ 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= 

Если вы хотите использовать MCRYPT_RIJNDAEL_128 вместо 256 на стороне PHP, это так же просто, как:

 from Crypto.Cipher import AES import base64 key="MyKey" def decrypt(text) cipher=AES.new(key) return cipher.decrypt(base64.b64decode(text)) 

Хотя ответ от @ 101100 был хорошим в то время, он больше не жизнеспособен. Ссылка теперь является неработающей ссылкой, и код будет работать только на старых Pythons (<3).

Вместо этого проект pprp, похоже, красиво заполняет пустоту. На Python 2 или Python 3 просто pip install pprp , затем:

 import pprp import base64 KEY_SIZE = 16 BLOCK_SIZE = 32 def encrypt(key, plaintext): key = key.encode('ascii') plaintext = plaintext.encode('utf-8') padded_key = key.ljust(KEY_SIZE, b'\0') sg = pprp.data_source_gen(plaintext, block_size=BLOCK_SIZE) eg = pprp.rjindael_encrypt_gen(padded_key, sg, block_size=BLOCK_SIZE) ciphertext = pprp.encrypt_sink(eg) encoded = base64.b64encode(ciphertext) return encoded.decode('ascii') def decrypt(key, encoded): key = key.encode('ascii') padded_key = key.ljust(KEY_SIZE, b'\0') ciphertext = base64.b64decode(encoded.encode('ascii')) sg = pprp.data_source_gen(ciphertext, block_size=BLOCK_SIZE) dg = pprp.rjindael_decrypt_gen(padded_key, sg, block_size=BLOCK_SIZE) return pprp.decrypt_sink(dg).decode('utf-8') key = 'MyKey' text = 'test' encoded = encrypt(key, text) print(repr(encoded)) # prints 'ju0pt5Y63Vj4qiViL4VL83Wjgirq4QsGDkj+tDcNcrw=' decoded = decrypt(key, encoded) print(repr(decoded)) # prints 'test' 

Я немного смущен тем, что зашифрованный текст отличается от того, что вы видите с ответом 101100. Однако я использовал этот метод для успешного дешифрования данных, зашифрованных в PHP, как описано в OP.