以SagePay网关形式将mcrypt升级为OpenSSL加密
目前,我们的SagePay网关表单中有mcyrpt加密,这在PHP7.4中不可用或不受支持 有人知道如何将下面的代码从mcyrpt更改为OpenSSL吗以SagePay网关形式将mcrypt升级为OpenSSL加密,openssl,opayo,Openssl,Opayo,目前,我们的SagePay网关表单中有mcyrpt加密,这在PHP7.4中不可用或不受支持 有人知道如何将下面的代码从mcyrpt更改为OpenSSL吗 // AES encryption, CBC blocking with PKCS5 padding then HEX encoding. // Add PKCS5 padding to the text to be encypted. $string = self::addPKCS5Padding($string);
// AES encryption, CBC blocking with PKCS5 padding then HEX encoding.
// Add PKCS5 padding to the text to be encypted.
$string = self::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));
}
/**
* Decode a returned string from SagePay.
*
* @param string $strIn The encrypted String.
* @param string $password The encyption password used to encrypt the string.
*
* @return string The unecrypted string.
* @throws SagepayApiException
*/
static public function decryptAes($strIn, $password)
{
// HEX decoding then AES decryption, CBC blocking with PKCS5 padding.
// Use initialization vector (IV) set from $str_encryption_password.
$strInitVector = $password;
// Remove the first char which is @ to flag this is AES encrypted and HEX decoding.
$hex = substr($strIn, 1);
// Throw exception if string is malformed
if (!preg_match('/^[0-9a-fA-F]+$/', $hex))
{
throw new SagepayApiException('Invalid encryption string');
}
$strIn = pack('H*', $hex);
// Perform decryption with PHP's MCRYPT module.
$string = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $password, $strIn, MCRYPT_MODE_CBC, $strInitVector);
return self::removePKCS5Padding($string);
}
下面是我们正在尝试的OpenSSL代码,但它需要一些调整,任何关于我们需要更改什么以获得OpenSSL代码来取代上述mcyrpt的建议都将不胜感激 发布的openssl代码有效,即使用encrypt\u openssl
加密的明文可以使用decrypt\u openssl
解密。但是,openssl代码在功能上与mcrypt代码不同,即使用mcrypt代码加密的数据不能使用openssl代码解密,反之亦然
我不太清楚工作流程,但我怀疑mcrypt代码的加密和解密逻辑也被SagePay网关使用,因此通信时必须确保openssl
代码在功能上与mcrypt
代码相同(尽管openssl
代码的实现比mcrypt代码更安全)
不幸的是,代码的重要部分没有发布,例如加密方法不完整,addPKCS5Padding
和removePKCS5Padding
完全缺失,因此必须处理部分假设
关于mcrypt规范,适用于:
- AES-128用于CBC模式。AES-128需要16字节的密钥
- 由于IV使用了密钥。请注意,这通常是不安全的
- mcrypt本身隐式地在变量中应用零填充,即如果明文的长度已经对应于块大小的整数倍,则不执行填充。因为使用PKCS5(实际上是PKCS7)自定义填充首先完成,mcrypt填充不会生效,因此有效地应用了PKCS5填充。不幸的是,addPKCS5Padding和removePKCS5Padding的实现未发布,因此无法检查它们是否都符合标准。解密后,PKCS5填充将被删除(与mcrypt内置的零填充不同)
- 加密使用大写字母对密文执行十六进制编码,并在其前面加上
@
- openssl默认使用PKCS7填充(在解密过程中默认删除),这在功能上与mcrypt代码中使用的填充相同(至少在mcrypt代码中使用的自定义PKCS5填充与标准匹配的情况下)
返回默认编码的密文Base64(openssl\u decrypt也需要此编码)。标志openssl\u encrypt
导致openssl\u encrypt将数据作为原始数据返回(openssl\u decrypt也需要原始数据)openssl\u RAW\u DATA
function encrypt_openssl($msg, $key, $iv) {
$encryptedMessage = openssl_encrypt($msg, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
return '@' . strtoupper(bin2hex($encryptedMessage));
}
function decrypt_openssl($encMsg, $key, $iv) {
$encMsg = substr($encMsg, 1);
// your validation stuff
$encMsg = hex2bin($encMsg);
return openssl_decrypt($encMsg, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
}
编辑:
这两种方法addPKCS5Padding
和removePKCS5Padding
符合PKCS7标准。无需修改。这些函数不得在openssl函数中使用,因为openssl隐式使用PKCS7填充,因此将填充两次,这将导致不同的密文
SagePay代码的加密与我发布的openssl函数的加密相匹配,这一点很容易测试:
使用SagePay代码进行加密(可执行代码,例如选择V7.0.x或更低版本):
使用openssl函数进行加密(例如,可以执行代码):
加密和解密都匹配。发布的openssl代码有效,即使用encrypt\u openssl
加密的明文可以使用decrypt\u openssl
进行解密。但是,openssl代码在功能上与mcrypt代码不同,即使用mcrypt代码加密的数据无法使用openssl co进行解密德,反之亦然
我不太清楚工作流程,但我怀疑mcrypt代码的加密和解密逻辑也被SagePay网关使用,因此通信时必须确保openssl
代码在功能上与mcrypt
代码相同(尽管openssl
代码的实现比mcrypt代码更安全)
不幸的是,代码的重要部分没有发布,例如加密方法不完整,addPKCS5Padding
和removePKCS5Padding
完全缺失,因此必须处理部分假设
关于mcrypt规范,适用于:
- AES-128用于CBC模式。AES-128需要16字节的密钥
- 由于IV使用了密钥。请注意,这通常是不安全的
- mcrypt本身隐式地在变量中应用零填充,即如果明文的长度已经对应于块大小的整数倍,则不执行填充。因为使用PKCS5(实际上是PKCS7)自定义填充首先完成,mcrypt填充不会生效,因此有效地应用了PKCS5填充。不幸的是,addPKCS5Padding和removePKCS5Padding的实现未发布,因此无法检查它们是否都符合标准。解密后,PKCS5填充将被删除(与mcrypt内置的零填充不同)
- 加密使用大写字母对密文执行十六进制编码,并在其前面加上
@
- openssl默认使用PKCS7填充(在解密过程中默认删除),这在功能上与mcrypt代码中使用的填充相同(在
<?php class SagepayApiException extends Exception {} class SagePayTest { static public function encryptAes($string, $key) { $string = self::addPKCS5Padding($string); $crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $key); return "@" . strtoupper(bin2hex($crypt)); } static public function decryptAes($strIn, $password) { $strInitVector = $password; $hex = substr($strIn, 1); if (!preg_match('/^[0-9a-fA-F]+$/', $hex)) { throw new SagepayApiException('Invalid encryption string'); } $strIn = pack('H*', $hex); $string = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $password, $strIn, MCRYPT_MODE_CBC, $strInitVector); return self::removePKCS5Padding($string); } static protected function addPKCS5Padding($input) { $blockSize = 16; $padd = ""; $length = $blockSize - (strlen($input) % $blockSize); for ($i = 1; $i <= $length; $i++) { $padd .= chr($length); } return $input . $padd; } static protected function removePKCS5Padding($input) { $blockSize = 16; $padChar = ord($input[strlen($input) - 1]); if ($padChar > $blockSize) { throw new SagepayApiException('Invalid encryption string'); } if (strspn($input, chr($padChar), strlen($input) - $padChar) != $padChar) { throw new SagepayApiException('Invalid encryption string'); } $unpadded = substr($input, 0, (-1) * $padChar); if (preg_match('/[[:^print:]]/', $unpadded)) { throw new SagepayApiException('Invalid encryption string'); } return $unpadded; } } $plaintext = "The quick brown fox jumps over the lazy dog"; $testkey = "95tjbs763khd9zh7"; $encrypted = SagePayTest::encryptAes($plaintext, $testkey); $decrypted = SagePayTest::decryptAes($encrypted, $testkey); print("Ciphertext (hex): " . $encrypted . PHP_EOL); print("Decrypted (hex): " . bin2hex($decrypted) . PHP_EOL); print("Decrypted : " . $decrypted . PHP_EOL); ?>
Ciphertext (hex): @67D4D4E0019BA7D0E75CC92C41488EF13613C1ED8A95B60E56347D1514AC5D7AF780F4314CA047A487AB67DF2D94174A Decrypted (hex): 54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67 Decrypted : The quick brown fox jumps over the lazy dog
<?php function encrypt_openssl($msg, $key, $iv) { $encryptedMessage = openssl_encrypt($msg, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); return '@' . strtoupper(bin2hex($encryptedMessage)); } function decrypt_openssl($encMsg, $key, $iv) { $encMsg = substr($encMsg, 1); // your validation stuff $encMsg = hex2bin($encMsg); return openssl_decrypt($encMsg, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); } $plaintext = "The quick brown fox jumps over the lazy dog"; $testkey = "95tjbs763khd9zh7"; $encrypted = encrypt_openssl($plaintext, $testkey, $testkey); $decrypted = decrypt_openssl($encrypted, $testkey, $testkey); print("Ciphertext (hex): " . $encrypted . PHP_EOL); print("Decrypted (hex): " . bin2hex($decrypted) . PHP_EOL); print("Decrypted : " . $decrypted . PHP_EOL); ?>
Ciphertext (hex): @67D4D4E0019BA7D0E75CC92C41488EF13613C1ED8A95B60E56347D1514AC5D7AF780F4314CA047A487AB67DF2D94174A Decrypted (hex): 54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67 Decrypted : The quick brown fox jumps over the lazy dog