В Java encrypt
-методе (случайно сгенерированные) солевые и IV-байты копируются вместе с байтами шифрования в один байтовый массив, который становится base64-кодированным и которыйвернулся тогда.Напротив, PHP encrypt
-метод возвращает шестнадцатеричное представление только байтов шифрования.Таким образом, информация, касающаяся соли и IV, теряется, и дешифрование больше невозможно (если соль и IV не реконструированы другими способами).Чтобы предотвратить это, вы должны изменить PHP encrypt
-метод следующим образом:
public function encrypt($data = '', $key = NULL) {
if($key != NULL && $data != ""){
$method = "AES-256-CBC";
$key1 = mb_convert_encoding($key, "UTF-8"); //Encoding to UTF-8
//Randomly generate IV and salt
$salt1 = random_bytes (20);
$IVbytes = random_bytes (16);
//SecretKeyFactory Instance of PBKDF2WithHmacSHA1 Java Equivalent
$hash = openssl_pbkdf2($key1,$salt1,'256','65556', 'sha1');
// Encrypt
$encrypted = openssl_encrypt($data, $method, $hash, OPENSSL_RAW_DATA, $IVbytes);
// Concatenate salt, IV and encrypted text and base64-encode the result
$result = base64_encode($salt1.$IVbytes.$encrypted);
return $result;
}else{
return "String to encrypt, Key is required.";
}
}
Теперь параметр $result
является строкой в кодировке base64, содержащейсоль, IV и шифрование.Кстати, параметры $salt1
и $IVbytes
теперь также генерируются случайным образом (аналог Java encrypt
-метода).Более того, число итераций, используемых для генерации ключа, было изменено с 65536 на 65556 (аналог Java encrypt
-метода).Примечание. Как правило, зашифрованный текст не воспроизводится (даже в случае одинакового простого текста и одного и того же ключа / пароля) из-за случайной природы соли и IV.
* Javadecrypt
-метод декодирует строку, закодированную в base64, а затем определяет три части, т.е. соли, IV и байты шифрования, необходимые для дешифрования. PHP decrypt
-метод должен быть дополнен следующими функциями:
public function decrypt($data="", $key = NULL) {
if($key != NULL && $data != ""){
$method = "AES-256-CBC";
$key1 = mb_convert_encoding($key, "UTF-8");//Encoding to UTF-8
// Base64-decode data
$dataDecoded = base64_decode($data);
// Derive salt, IV and encrypted text from decoded data
$salt1 = substr($dataDecoded,0,20);
$IVbytes = substr($dataDecoded,20,16);
$dataEncrypted = substr($dataDecoded,36);
// SecretKeyFactory Instance of PBKDF2WithHmacSHA1 Java Equivalent
$hash = openssl_pbkdf2($key1,$salt1,'256','65556', 'sha1');
// Decrypt
$decrypted = openssl_decrypt($dataEncrypted, $method, $hash, OPENSSL_RAW_DATA, $IVbytes);
return $decrypted;
}else{
return "Encrypted String to decrypt, Key is required.";
}
}
Теперь параметр $dataDecoded
содержит декодированную строку в кодировке base64, из которой salt- (*)Получены байты 1030 *), IV- ($IVbytes
) и шифрования ($dataEncrypted
).Более того, число итераций, используемых для генерации ключей, было изменено с 65536 на 65556 (аналогично методу Java decrypt
).
Тестовый пример 1: шифрование и дешифрование с помощью PHP
$atomAES = new AtomAES();
$encrypt = $atomAES->encrypt("This is a text...This is a text...This is a text...", "This is the password");
echo $encrypt;
$decrypt = $atomAES->decrypt($encrypt, "This is the password");
echo $decrypt;
с результатом для $encrypt
(который, как правило, отличается для каждого шифрования из-за случайного характера соли и IV):
6n4V9wqgsQq87HOYNRZmddnncSNyjFZZb8nSSAi681+hs+jwzDVQCugcg108iTMZLlmBB2KQ4iist+SuboFH0bnJxW6+rmZK07CiZ1Ip+8XOv6UuJPjVPxXTIny5p3QptpBGpw==
и для $decrypt
:
This is a text...This is a text...This is a text...
Контрольный пример 2: шифрование с Java, дешифрование с помощью PHP
encryptedText = AES256.encrypt("This is a text...This is a text...This is a text...","This is the password");
System.out.println(encryptedText);
с результатом для encryptedText
(который, как правило, отличается для каждогошифрование из-за случайной природы соли и IV):
qfR76lc04eYAPjjqYiE1wXoraD9bI7ql41gSV/hsT/BLoJe0i0GgJnud7IXOHdcCljgtyFkXB95XibSyr/CazoMhwPeK6xsgPbQkr7ljSg8H1i17c8iWpEXBQPm0nij9qQNJ8A==
и
$decrypt = $atomAES->decrypt("qfR76lc04eYAPjjqYiE1wXoraD9bI7ql41gSV/hsT/BLoJe0i0GgJnud7IXOHdcCljgtyFkXB95XibSyr/CazoMhwPeK6xsgPbQkr7ljSg8H1i17c8iWpEXBQPm0nij9qQNJ8A==", "This is the password");
echo $decrypt;
с результатом для $decrypt
:
This is a text...This is a text...This is a text...
Тестовый пример 3: Шифрование с Java, Расшифровка с помощью PHP
encryptedText = AES256.encrypt("This is a sample text","NEWENCTEST");
System.out.println(encryptedText);
1HO8iuSZf41RzP/gUleEJY3zhtLJVwFMnhZiphnoG0m9ss+g93Sj5SqQg0D7OsgSvUZCeX2Ck5QPpFrPxM0FE/yFE5s=
и
$decrypt = $atomAES->decrypt("1HO8iuSZf41RzP/gUleEJY3zhtLJVwFMnhZiphnoG0m9ss+g93Sj5SqQg0D7OsgSvUZCeX2Ck5QPpFrPxM0FE/yFE5s=", "NEWENCTEST");
echo $decrypt;
с результатом для $decrypt
:
This is a sample text