Here's the brief from the payment gateway (Elavon):
The string must be encrypted using AES (block size 128-bit) in CBC mode with PKCS#5 padding. Use the provided password as both the key and initialisation vector and encode the result in hex (making sure the letters are in upper case). Prepend the ‘@’ sign to the beginning of the encoded result.
Here's my code:
function encryptAesTest($string, $key)
{
$cipher = "aes-128-cbc";
$crypt = openssl_encrypt($string, $cipher, $key, 0, $key);
return "@" . strtoupper(bin2hex($crypt));
}
The question is, does this code satisfy the brief from the payment gateway ?
I am attempting to convert from mcrypt_encrypt -> openssl_encrypt
My PHP version is 8.2.13
I think I might be going wrong with PKCS#5 padding as I understand that openssl_encrypt uses PKCS#7 padding
The error message from Elavon (SagePay) is unhelpful:
5080 : Form transaction registration failed.
Any help would be greatly appreciated
The document Sage Pay Form Integration and Protocol Guidelines 3.00 (see sec. A1.2 Example Crypt Field, p. 38) contains test data (in sec. A1.1 The Crypt field you will also find the specification that corresponds to yours):
If in the posted code the default Base64 encoding in
openssl_encrypt()is disabled withOPENSSL_RAW_DATA, the code works. Using the above password and plaintext results in the expected ciphertext!Fixed PHP code:
Security: The protocol has the following vulnerabilities:
The key seems to be a hex encoded value, which limits the range of values per key byte from 256 to 16 (so effectively only an 8 byte key is used instead of a 16 byte key), which is a serious vulnerability.
In addition, the use of the key as IV is a vulnerability since this results in the reuse of key/IV pairs.