2016-09-25 5 views
3

Я работаю над проектом, где PHP используется для расшифровки сообщений AES-256-CBCPHP OpenSSL AES в Python

<?php 

class CryptService{ 
    private static $encryptMethod = 'AES-256-CBC'; 
    private $key; 
    private $iv; 

    public function __construct(){ 
     $this->key = hash('sha256', 'c7b35827805788e77e41c50df44441491098be42'); 
     $this->iv = substr(hash('sha256', 'c09f6a9e157d253d0b2f0bcd81d338298950f246'), 0, 16); 
    } 

    public function decrypt($string){ 
     $string = base64_decode($string); 
     return openssl_decrypt($string, self::$encryptMethod, $this->key, 0, $this->iv); 
    } 

    public function encrypt($string){ 
     $output = openssl_encrypt($string, self::$encryptMethod, $this->key, 0, $this->iv); 
     $output = base64_encode($output); 
     return $output; 
    } 
} 

$a = new CryptService; 
echo $a->encrypt('secret'); 
echo "\n"; 
echo $a->decrypt('S1NaeUFaUHdqc20rQWM1L2ZVMDJudz09'); 
echo "\n"; 

ouutput

>>> S1NaeUFaUHdqc20rQWM1L2ZVMDJudz09 
>>> secret 

Теперь я должен написать Python 3 код шифрование данных. Я пробовал использовать PyCrypto, но безуспешно. Мой код:

import base64 
import hashlib 
from Crypto.Cipher import AES 

class AESCipher: 
    def __init__(self, key, iv): 
     self.key = hashlib.sha256(key.encode('utf-8')).digest() 
     self.iv = hashlib.sha256(iv.encode('utf-8')).digest()[:16] 

    __pad = lambda self,s: s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) % AES.block_size) 
    __unpad = lambda self,s: s[0:-ord(s[-1])] 

    def encrypt(self, raw): 
     raw = self.__pad(raw) 
     cipher = AES.new(self.key, AES.MODE_CBC, self.iv) 
     return base64.b64encode(cipher.encrypt(raw)) 

    def decrypt(self, enc): 
     enc = base64.b64decode(enc) 
     cipher = AES.new(self.key, AES.MODE_CBC, self.iv) 
     return self.__unpad(cipher.decrypt(enc).decode("utf-8")) 

cipher = AESCipher('c7b35827805788e77e41c50df44441491098be42', 'c09f6a9e157d253d0b2f0bcd81d338298950f246') 

enc_str = cipher.encrypt("secret") 
print(enc_str) 

выход

>>> b'tnF87LsVAkzkvs+gwpCRMg==' 

Но мне нужен выход S1NaeUFaUHdqc20rQWM1L2ZVMDJudz09, который PHP расшифровывать для secret. Как изменить код Python для получения ожидаемого результата?

ответ

3

PHP's hash выводит по шестнадцатеричной строке по умолчанию, но .digest() Python возвращает bytes. Вы, наверное, хотели использовать .hexdigest():

def __init__(self, key, iv): 
    self.key = hashlib.sha256(key.encode('utf-8')).hexdigest()[:32].encode("utf-8") 
    self.iv = hashlib.sha256(iv.encode('utf-8')).hexdigest()[:16].encode("utf-8") 

Идея вектора инициализации (IV) является обеспечение рандомизации для шифрования с тем же ключом. Если вы используете тот же IV, злоумышленник может вывести, что вы отправляете одно и то же сообщение дважды. Это можно рассматривать как нарушенный протокол.

IV не должен быть секретным, поэтому вы можете просто отправить его вместе с зашифрованным текстом. Обычно перед расшифровкой его перед шифровым текстом следует зашифровать до шифрования.

+0

Спасибо Artjom. Еще одна вещь, которую мне пришлось изменить, - это двойной вызов 'base64.b64encode' в' encrypt'. После этого я получаю тот же вывод от Python, что и PHP. Я не знаю, почему в PHP вызывается 'base64_encode', хотя' openssl_encrypt' возвращает результат с кодировкой base64. –

+0

Возможно, это так, потому что оригинальный разработчик понятия не имел, что они делают. –

 Смежные вопросы

  • Нет связанных вопросов^_^