Im attempting to integrate the SagePay payment gateway into a website using the 'Form Integration' method.
Basically the form integration method works by inserting a FORM in a webpage and POSTing information to SagePay's servers whenever the Submit button for the FORM is selected. Before the information can be sent to SagePay's servers it must be encrypted using the AES/CBC/PKCS#5 algorithm, before being Base 64 encoded.
I have a basic knowledge of encryption but I have no experience of using it in PHP. Can anyone please help me formulate the AES/CBC/PKCS#5 algorithm in PHP please?
Here's my efforts so far:
$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>";
Any help is much appreciated.
Here is a working implementation of AES/CBC/PKCS#5 working with Sagepay's form integration You will need mcrypt installed. sp_encryption is a define for the encryption key.
/**
* @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);
}
On a side note make sure the VPSProtocol you use is '3.00' not 3, and not 3.0 as these won't work!
Hoep this helps and sagepay get some official PHP docs out soon.
Yes, that's fine. (As soon as we have a PHP kit for v3.00 we'll display it on our website).
Hope the below helps you to.
Example:
AES encryption with Base64 encoding AES encryption, CBC blocking with PKCS5 padding then HEX encoding
//** 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));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With