Я работаю над проектом, где PHP используется для расшифровки сообщений AES-256-CBC
<?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, чтобы получить ожидаемый результат?
РНР hash
выводит шестнадцатеричную строку по умолчанию, но Python .digest()
возвращается 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 не должен быть секретным, поэтому вы можете просто отправить его вместе с зашифрованным текстом. Во время шифрования принято добавлять его к зашифрованному тексту и вырезать его перед расшифровкой.
Других решений пока нет …