没有 mcrypt 的 Sagepay 集成
Sagepay integration without mcrypt
我希望使用他们在此处的指导与 Sagepay/Opayo Form 集成:
https://www.sagepay.co.uk/file/25041/download-document/FORM_Integration_and_Protocol_Guidelines_270815.pdf?token=Cfj49hcaD4kpE0zk7179ZLOaQx2RH_3oatPOrAV6MyM
Sagepay 现在已停止支持 SDK,这意味着我必须从这里找到 2013 实用程序集:
https://github.com/ammaar23/sagepay-sdk-php/blob/master/lib/classes/util.php
我正在尝试从 mcrypt 迁移到 openssl_encrypt
,但似乎无法复制所需的结果。
有 2 个函数在起作用:
static protected 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;
}
static public function encryptAes($string, $key)
{
// AES encryption, CBC blocking with PKCS5 padding then HEX encoding.
// Add PKCS5 padding to the text to be encypted.
$string = self::addPKCS5Padding($string);
// AH updated as mcrypt is now deprecated! 2020
$cipher = 'AES-128-CBC';
$ivsize = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivsize);
$crypt = openssl_encrypt($string,$cipher,$key,0,$iv);
// Perform hex encoding and return.
return "@" . strtoupper(bin2hex($crypt));
}
您可以看到我尝试实施 openssl_encrypt 但它不起作用。键是55a51621a6648525
,输入字符串是VendorTxCode=TxCode-1310917599-223087284&Amount=36.95&Currency=GBP&Description=description&CustomerName=Fname Surname&CustomerEMail=customer@example.com&BillingSurname=Surname&BillingFirstnames=Fname&BillingAddress1=BillAddress Line 1&BillingCity=BillCity&BillingPostCode=W1A 1BL&BillingCountry=GB&BillingPhone=447933000000&DeliveryFirstnames=Fname&DeliverySurname=Surname&DeliveryAddress1=BillAddress Line 1&DeliveryCity=BillCity&DeliveryPostCode=W1A 1BL&DeliveryCountry=GB&DeliveryPhone=447933000000&SuccessURL=https://example.com/success&FailureURL=https://example.com/failure
输出结果为:
@2DCD27338114D4C39A14A855702FBAB2EF40BCAC2D76A3ABC0F660A07E9C1C921C2C755BA9B59C39F882FBF6DFED114F23141D94E50A01A665B1E31A86C07CA1CD1BB8EF5B6CF2C23D495CD 79F9C0F678D61773E7A1AA30AA5B23D56503FC0B52AC0694A8C341263D2C5FE1BAD93BDB94726761E155E900448F644AF1F67BE1AC77E852B9D90809A44F258EE9478B6D8C1C4ED58759263E7DBF 8871C6592287C0358F36F4EEC326CEDDD440DA2FED8AB35F1B630A5C6FA671E4D78CC8CACECF9DFDC31D6C5EC8270FB21E297E2C2E14F99A04223EFFD4F00062D440E78A3D2C7140EC8F123D24 7B75E7482AE98858DA34D37EDE6D7C69AA74391F559305CF675ADB3615244A107ABBB6AF26E29A2FFA059B12688D90FE09E0DE069325BFF3587A695F5DA36E4B809B69CC9A37034F166B63B5A62 B986F4DA34E9AC9516AFDE70642EC7DAD1AEBA93A1F347D6AC7046E967DCBFE7ACFCEE5DAFC0B29F1765032B3060EBE565CBD57D092075D15CF12725199C6881605B2E0F105698CE3ADD04361C A9D620C187B90E3F9849445B5C3C0FDF1768BFFD61F97E51316826F4F10E0E3E668F0A9F5ED9CCDA6F2C7CC957F12DB48F9041482E3D035E7A91852C404BFA325FED947E71F57B871DFAC6AF4FF2 9F4513A4A80B2D7ECC9D19D47ED04FA99CDFC881DFA771E1EA4F3F9B2C5AC673EF3DA2699A309CC8522993A63CB8D45D3CDF09B1DFDC573CD19679B250AD6721450B5042F201670B464505DCAE F59E2C67ABACC9AE2EEE793CE191FEBF66B8FAF4204EFFB359246B9C99FB52805C46375FF35140F74707FBC73C7731A28A2C883A
我如何从我的输入代码创建所需的输出,因为我生成的输出开头为:403444324634333730363535313636373136413432363737353332363133303644373736
openssl_encrypt
默认应用 PKCS7 填充,因此不再需要 addPKCS5Padding
方法。
- 在
mcrypt_encrypt
代码中使用了 iv = key,因此您不能为代码等价生成随机 IV。
- 在
openssl_encrypt
中,标志OPENSSL_RAW_DATA
必须作为第四个参数应用,否则数据将以Base64编码返回。
经过这些更改,openssl_encrypt
代码产生与 mcrypt_encrypt
代码相同的结果:
<?php
function encryptAes($string, $key)
{
//$string = self::addPKCS5Padding($string); // don't pad explicitly
$cipher = 'AES-128-CBC';
//$ivsize = openssl_cipher_iv_length($cipher);
//$iv = openssl_random_pseudo_bytes($ivsize); // mcrypt_encrypt code: iv = key
$crypt = openssl_encrypt($string,$cipher,$key,OPENSSL_RAW_DATA,$key); // use raw data
return "@" . strtoupper(bin2hex($crypt));
}
$plain = "VendorTxCode=TxCode-1310917599-223087284&Amount=36.95&Currency=GBP&Description=description&CustomerName=Fname Surname&CustomerEMail=customer@example.com&BillingSurname=Surname&BillingFirstnames=Fname&BillingAddress1=BillAddress Line 1&BillingCity=BillCity&BillingPostCode=W1A 1BL&BillingCountry=GB&BillingPhone=447933000000&DeliveryFirstnames=Fname&DeliverySurname=Surname&DeliveryAddress1=BillAddress Line 1&DeliveryCity=BillCity&DeliveryPostCode=W1A 1BL&DeliveryCountry=GB&DeliveryPhone=447933000000&SuccessURL=https://example.com/success&FailureURL=https://example.com/failure";
$key = "55a51621a6648525";
print(encryptAes($plain, $key));
?>
对于选择 iv = key note 还有 this question 的答案。
@Topaco 回答得很好。这是一个附加位,(与问题无关),在进行 Sagepay 集成时,您还需要解密功能来验证 payment/callback。这是您可以使用的功能。
function decrypytAES($string, $key) {
$cipher = 'AES-128-CBC';
$strIn = hex2bin(substr($strIn, 1));
return openssl_decrypt($strIn, $cipher, $key, OPENSSL_RAW_DATA, $key);
}
我希望使用他们在此处的指导与 Sagepay/Opayo Form 集成: https://www.sagepay.co.uk/file/25041/download-document/FORM_Integration_and_Protocol_Guidelines_270815.pdf?token=Cfj49hcaD4kpE0zk7179ZLOaQx2RH_3oatPOrAV6MyM
Sagepay 现在已停止支持 SDK,这意味着我必须从这里找到 2013 实用程序集: https://github.com/ammaar23/sagepay-sdk-php/blob/master/lib/classes/util.php
我正在尝试从 mcrypt 迁移到 openssl_encrypt
,但似乎无法复制所需的结果。
有 2 个函数在起作用:
static protected 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;
}
static public function encryptAes($string, $key)
{
// AES encryption, CBC blocking with PKCS5 padding then HEX encoding.
// Add PKCS5 padding to the text to be encypted.
$string = self::addPKCS5Padding($string);
// AH updated as mcrypt is now deprecated! 2020
$cipher = 'AES-128-CBC';
$ivsize = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivsize);
$crypt = openssl_encrypt($string,$cipher,$key,0,$iv);
// Perform hex encoding and return.
return "@" . strtoupper(bin2hex($crypt));
}
您可以看到我尝试实施 openssl_encrypt 但它不起作用。键是55a51621a6648525
,输入字符串是VendorTxCode=TxCode-1310917599-223087284&Amount=36.95&Currency=GBP&Description=description&CustomerName=Fname Surname&CustomerEMail=customer@example.com&BillingSurname=Surname&BillingFirstnames=Fname&BillingAddress1=BillAddress Line 1&BillingCity=BillCity&BillingPostCode=W1A 1BL&BillingCountry=GB&BillingPhone=447933000000&DeliveryFirstnames=Fname&DeliverySurname=Surname&DeliveryAddress1=BillAddress Line 1&DeliveryCity=BillCity&DeliveryPostCode=W1A 1BL&DeliveryCountry=GB&DeliveryPhone=447933000000&SuccessURL=https://example.com/success&FailureURL=https://example.com/failure
输出结果为:
@2DCD27338114D4C39A14A855702FBAB2EF40BCAC2D76A3ABC0F660A07E9C1C921C2C755BA9B59C39F882FBF6DFED114F23141D94E50A01A665B1E31A86C07CA1CD1BB8EF5B6CF2C23D495CD 79F9C0F678D61773E7A1AA30AA5B23D56503FC0B52AC0694A8C341263D2C5FE1BAD93BDB94726761E155E900448F644AF1F67BE1AC77E852B9D90809A44F258EE9478B6D8C1C4ED58759263E7DBF 8871C6592287C0358F36F4EEC326CEDDD440DA2FED8AB35F1B630A5C6FA671E4D78CC8CACECF9DFDC31D6C5EC8270FB21E297E2C2E14F99A04223EFFD4F00062D440E78A3D2C7140EC8F123D24 7B75E7482AE98858DA34D37EDE6D7C69AA74391F559305CF675ADB3615244A107ABBB6AF26E29A2FFA059B12688D90FE09E0DE069325BFF3587A695F5DA36E4B809B69CC9A37034F166B63B5A62 B986F4DA34E9AC9516AFDE70642EC7DAD1AEBA93A1F347D6AC7046E967DCBFE7ACFCEE5DAFC0B29F1765032B3060EBE565CBD57D092075D15CF12725199C6881605B2E0F105698CE3ADD04361C A9D620C187B90E3F9849445B5C3C0FDF1768BFFD61F97E51316826F4F10E0E3E668F0A9F5ED9CCDA6F2C7CC957F12DB48F9041482E3D035E7A91852C404BFA325FED947E71F57B871DFAC6AF4FF2 9F4513A4A80B2D7ECC9D19D47ED04FA99CDFC881DFA771E1EA4F3F9B2C5AC673EF3DA2699A309CC8522993A63CB8D45D3CDF09B1DFDC573CD19679B250AD6721450B5042F201670B464505DCAE F59E2C67ABACC9AE2EEE793CE191FEBF66B8FAF4204EFFB359246B9C99FB52805C46375FF35140F74707FBC73C7731A28A2C883A
我如何从我的输入代码创建所需的输出,因为我生成的输出开头为:403444324634333730363535313636373136413432363737353332363133303644373736
openssl_encrypt
默认应用 PKCS7 填充,因此不再需要addPKCS5Padding
方法。- 在
mcrypt_encrypt
代码中使用了 iv = key,因此您不能为代码等价生成随机 IV。 - 在
openssl_encrypt
中,标志OPENSSL_RAW_DATA
必须作为第四个参数应用,否则数据将以Base64编码返回。
经过这些更改,openssl_encrypt
代码产生与 mcrypt_encrypt
代码相同的结果:
<?php
function encryptAes($string, $key)
{
//$string = self::addPKCS5Padding($string); // don't pad explicitly
$cipher = 'AES-128-CBC';
//$ivsize = openssl_cipher_iv_length($cipher);
//$iv = openssl_random_pseudo_bytes($ivsize); // mcrypt_encrypt code: iv = key
$crypt = openssl_encrypt($string,$cipher,$key,OPENSSL_RAW_DATA,$key); // use raw data
return "@" . strtoupper(bin2hex($crypt));
}
$plain = "VendorTxCode=TxCode-1310917599-223087284&Amount=36.95&Currency=GBP&Description=description&CustomerName=Fname Surname&CustomerEMail=customer@example.com&BillingSurname=Surname&BillingFirstnames=Fname&BillingAddress1=BillAddress Line 1&BillingCity=BillCity&BillingPostCode=W1A 1BL&BillingCountry=GB&BillingPhone=447933000000&DeliveryFirstnames=Fname&DeliverySurname=Surname&DeliveryAddress1=BillAddress Line 1&DeliveryCity=BillCity&DeliveryPostCode=W1A 1BL&DeliveryCountry=GB&DeliveryPhone=447933000000&SuccessURL=https://example.com/success&FailureURL=https://example.com/failure";
$key = "55a51621a6648525";
print(encryptAes($plain, $key));
?>
对于选择 iv = key note 还有 this question 的答案。
@Topaco 回答得很好。这是一个附加位,(与问题无关),在进行 Sagepay 集成时,您还需要解密功能来验证 payment/callback。这是您可以使用的功能。
function decrypytAES($string, $key) {
$cipher = 'AES-128-CBC';
$strIn = hex2bin(substr($strIn, 1));
return openssl_decrypt($strIn, $cipher, $key, OPENSSL_RAW_DATA, $key);
}