我有一个收集数据的表格,然后将其提交给SagePay,并传递数据。在我们需要更新到PHP 7.2之前,它一直工作良好,并且由于不再支持mcrypt,我们将切换到OpenSSL。
收集数据的形式工作正常,但传输数据未加密,交易失败。
功能文件中的代码:
$protx_encryption_password = "my_password";
$protx_vendor = "my_vendor";
$data = "";
while(list($key,$value) = each($protx)) {
$data .= $key."=".$value."&";
}
$data = trim($data," &");
$crypt = openssl_encrypt($data, $protx_encryption_password);
function openssl_encrypt($string, $key) {
$iv = substr($value, 0, 16);
$ciphertext = substr($value, 16);
$key = hash('sha256', $key, true);
$crypt = openssl_encrypt(
$ciphertext, 'AES-256-CBC', $key,
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
$iv
);
return rtrim($crypt, "\0");
}
$ crypt数据像以前在mcrypt版本中一样在隐藏字段中发送,我只需要一些帮助才能使加密正常工作。
以前以mcrypt方式:
$crypt = encryptAes($data, $protx_encryption_password);
function encryptAes($string, $key) {
// AES encryption, CBC blocking with PKCS5 padding then HEX encoding.
// Add PKCS5 padding to the text to be encypted.
$string = addPKCS5Padding($string);
// Perform encryption with PHP's MCRYPT module.
$crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $key);
// Perform hex encoding and return.
return "@" . strtoupper(bin2hex($crypt));
}
function addPKCS5Padding($input) {
$blockSize = 16;
$padd = "";
// Pad input to an even block size boundary.
$length = $blockSize - (strlen($input) % $blockSize);
for ($i = 1; $i <= $length; $i++)
{
$padd .= chr($length);
}
return $input . $padd;
}
这是我做过的第一个OpenSSL加密,因此,我很感谢您的协助。 SagePay需要使用PCKS#5(AES-128-CBC-PKCS#5)在CBC模式下使用128位块大小的AES-128加密进行加密。任何帮助都会真正有帮助。
首先,这是一个不好的方案。即使在可能的情况下,使用(真实)密码作为现代加密的密钥几乎总是不安全的。密码和密钥是不同的事物,它们的设计和指定是不同的。当然,有些人不知道自己在做什么[
也仅供参考,说“具有128位块的AES-128”毫无意义。 AES
always
使用128位块;那是建立它的竞争规则的一部分。 Rijndael确实具有其他块大小的选项,这就是为什么实现Rijndael的mcrypt或多或少地指定了块大小,而OpenSSL却实现了AES,而AES并不需要指定块大小- -only密钥大小。第二,您建议的新代码是胡说八道。首先,您尝试重新定义不允许的标准功能,然后清楚地将您提出的逻辑设计为解密,不加密,一种完全不同的方案,而不是您提出的方案,然后进行修改。mcrypt_encrypt
对明文进行零填充,在旧版本中,根据需要对键和iv进行零填充。对于Rijndael,它还根据提供的密钥来选择密钥大小。因为您说要使用AES-128(即128位密钥),所以所谓的“密码”不得超过128位,但可以少于128位。您发布的代码对数据进行了显式的PKCS5填充,因此未使用mcrypt的零填充,并且正如Peter所言,openssl_encrypt
(及其在下面使用的OpenSSL例程)默认情况下会进行PCKS5 / 7填充,因此您所需要的全部是:
function encryptAes_new ($string, $key) {
$key = str_pad($key,16,"\0"); # if supplied key is, or may be, less than 16 bytes
$crypt = openssl_encrypt($string, 'aes-128-cbc', $key, OPENSSL_RAW_DATA, $key);
// Perform hex encoding and return.
return "@" . strtoupper(bin2hex($crypt));
}
((注:原始PKCS5填充仅处理64位/ 8字节块,而PKCS7将其扩展为其他大小,但是2017年PKCS5v2.1也引用了CMS对其进行扩展,CMS是PKCS7的IETF版本,因此现在一样。)