【问题标题】:AES/CBC/PKCS#5 Encryption Algorithm In PHPPHP 中的 AES/CBC/PKCS#5 加密算法
【发布时间】:2013-11-26 08:37:36
【问题描述】:

我正在尝试使用“表单集成”方法将 SagePay 支付网关集成到网站中。

基本上,表单集成方法通过在网页中插入表单并在选择表单的提交按钮时将信息发布到 SagePay 的服务器来工作。在将信息发送到 SagePay 的服务器之前,必须使用 AES/CBC/PKCS#5 算法对其进行加密,然后再进行 Base 64 编码。

我有基本的加密知识,但我没有在 PHP 中使用它的经验。谁能帮我在 PHP 中制定 AES/CBC/PKCS#5 算法吗?

这是我目前所做的努力:

$CRYPT = "Text Goes Here";

$blocksize = 16;//Does 16 Refer To 16 Bytes Or 16 Bits? 16 Bytes = 128 Bits.
$cryptLength = strlen($CRYPT);
$cryptLengthModuloBlocksize = $cryptLength % $blocksize;
$pad = $blocksize - $cryptLengthModuloBlocksize;
$padString = str_repeat(chr($pad), $pad);
$CRYPT = $CRYPT . $padString;

$encryptionPassword = 'password';
$Encrypted_CRYPT = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $encryptionPassword, $CRYPT, MCRYPT_MODE_CBC);

$Base64_Encrypted_CRYPT = base64_encode($Encrypted_CRYPT);

echo    "<form action = 'https://test.sagepay.com/gateway/service/vspform-register.vsp' method = 'POST'>

            <input type = 'hidden' name = 'VPSProtocol' value = '3.00' />//
            <input type = 'hidden' name = 'TxType' value = 'PAYMENT' />
            <input type = 'hidden' name = 'Vendor' value = 'vendorName' />
            <input type = 'hidden' name = 'Crypt' value = '" . $Base64_Encrypted_CRYPT . "' />
            <input type= 'submit' value = 'Submit'>

        </form>";

非常感谢任何帮助。

【问题讨论】:

    标签: php encryption aes opayo


    【解决方案1】:

    这是 AES/CBC/PKCS#5 与 Sagepay 的表单集成一起使用的工作实现 您将需要安装 mcrypt。 sp_encryption 是加密密钥的定义。

    /**
    * @param string $data - the key=value pairs separated with & 
    * @return string
    */
    protected function encode_data($data) {
        $strIn = $this->pkcs5_pad($data);
        $strCrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, sp_encryption, $strIn, MCRYPT_MODE_CBC, sp_encryption);
        return "@" . bin2hex($strCrypt);
    }
    
    /**
    * @param string $data - crypt response from Sagepay
    * @return string
    */
    protected function decode_data($data) {
        if (substr($data, 0, 1) == "@") {
            $strIn = hex2bin(substr($data, 1));
            return $this->pkcs5_unpad(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, sp_encryption, $strIn, MCRYPT_MODE_CBC, sp_encryption));
        }
        return '';
    }
    
    protected function pkcs5_pad($text) {
    $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $pad = $size - (strlen($text) % $size);
        return $text . str_repeat(chr($pad), $pad);
    }
    
    protected function pkcs5_unpad($text) {
        $pad = ord($text{strlen($text) - 1});
        if ($pad > strlen($text)) return false;
        if (strspn($text, $text{strlen($text) - 1}, strlen($text) - $pad) != $pad) {
            return false;
        }
        return substr($text, 0, -1 * $pad);
    }
    

    附带说明,请确保您使用的 VPSProtocol 是“3.00”而不是 3,而不是 3.0,因为这些不起作用!

    希望这有助于 sagepay 尽快发布一些官方 PHP 文档。

    【讨论】:

      【解决方案2】:

      是的,没关系。 (一旦我们有了 v3.00 的 PHP 工具包,我们就会在我们的网站上展示它。

      希望以下内容对您有所帮助。

      例子:

      使用 Base64 编码的 AES 加密 AES 加密,使用 PKCS5 填充然后 HEX 编码的 CBC 阻塞

      //** Wrapper function do encrypt an encode based on strEncryptionType setting **
      function encryptAndEncode($strIn) {
      
      global $strEncryptionType
            ,$strEncryptionPassword;
      
      {
          //** AES encryption, CBC blocking with PKCS5 padding then HEX encoding **
      
          //** use initialization vector (IV) set from $strEncryptionPassword
          $strIV = $strEncryptionPassword;
      
          //** add PKCS5 padding to the text to be encypted
          $strIn = addPKCS5Padding($strIn);
      
          //** perform encryption with PHP's MCRYPT module
          $strCrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $strEncryptionPassword, $strIn, MCRYPT_MODE_CBC, $strIV);
      
          //** perform hex encoding and return
          return "@" . bin2hex($strCrypt);
      }
      }
      
      
      //** Wrapper function do decode then decrypt based on header of the encrypted field **
      function decodeAndDecrypt($strIn) {
      
      global $strEncryptionPassword;
      
      if (substr($strIn,0,1)=="@") 
      {
          //** HEX decoding then AES decryption, CBC blocking with PKCS5 padding  **
      
          //** use initialization vector (IV) set from $strEncryptionPassword
          $strIV = $strEncryptionPassword;
      
          //** remove the first char which is @ to flag this is AES encrypted
          $strIn = substr($strIn,1); 
      
          //** HEX decoding
          $strIn = pack('H*', $strIn);
      
          //** perform decryption with PHP's MCRYPT module
          return removePKCS5Padding(
              mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $strEncryptionPassword, $strIn, MCRYPT_MODE_CBC, $strIV));
      } 
      
      }
      

      【讨论】:

      • 非常感谢您回答@SagePaySupport。我已经测试了上面的代码,现在我不再收到 5068 加密错误。我确实注意到上面的代码使用 HEX 编码,而不是 SagePay 文档中所述的 Base64 编码。
      • 嗨,是的,上面使用了十六进制,因为可以使用不同的加密算法。我们较旧的 PHP 工具包有 base64 的示例(目前不可用,但很快将通过我们的网站集成文档>下载文档)。我们建议使用 base64,但我们认为这对您可以使用的示例有所帮助。很高兴您能够克服错误 5068,这很棒。
      【解决方案3】:

      您是否使用 PKCS5 填充,然后使用 HEX 编码,因为我们的旧 PHP 工具包使用了这个。

      您可能需要查看previous post 来比较您发送的内容。它使用的是较旧的协议 v2.23 和 XOR。如果您使用我们的新协议,您将使用 v3.00 和 AES。

      如果您想发送电子邮件至 feedback@sagepay.com,我们可以进一步讨论。请引用此论坛帖子网址。

      Sage 支付支持

      【讨论】:

      • 非常感谢您的回复@sagepaysupport。我正在使用协议的第 3 版。在使用 AES 加密之前,我正在 PKCS5 填充 CRYPT 字符串。在我使用 AES 加密字符串之后,然后我使用 BASE 64 对其进行编码。这是正确的方法吗?
      【解决方案4】:

      您可以在此处查看有效的 v3 示例:https://github.com/tolzhabayev/sagepayForm-php

      【讨论】:

      • 谢谢 - SagePay 网站应该链接到此作为临时措施,很棒的图书馆,谢谢!
      • 一段很棒的代码,虽然success.php似乎只为我返回错误,或者如果我添加了sagePay所需的php,它会返回一个带有奇怪字符的数组?帖木儿有什么建议吗?
      • @AndrewDover 是的,success.php 文件中应该需要 sagePay,我已经更改了示例。带有奇怪字符的数组是您从 sagepay 收到的响应。您可能不需要整个数组,只需支付状态和支付 ID 就足以将交易标记为成功
      • 感谢 Timur,让它成功运行! Sagepay 真的应该将您的出色工作放到他们的网站上!
      猜你喜欢
      • 1970-01-01
      • 2017-09-28
      • 2013-08-11
      • 2021-06-07
      • 2022-11-16
      • 2020-01-14
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多