I am getting information back from Visa Checkout in an encrypted format. The guide on their site provides these instructions:
First, you must decrypt the dynamic key (encKey), then use the decrypted dynamic key value to decrypt the payment data payload (encPaymentData).
Follow these four steps to decrypt the encKey:
- Base64-decode the encKey.
- Remove the first 32 bytes of the decoded value. This is the HMAC (Hash Message Authentication Code). Calculate a SHA-256 HMAC of the
rest of the decoded data using your API Shared Secret and compare it
to the HMAC from the first 32 bytes.- The next 16 bytes should be removed and used as the IV (Initialization Vector) for the decryption algorithm.
- Decrypt the remaining data using AES-256-CBC, the IV from step 3, and the SHA-256 hash of your API Shared Secret.
Follow these four steps to decrypt the encPaymentData using the decrypted encKey:
- Base64-decode the encPaymentData.
- Remove the first 32 bytes of the decoded value. This is the HMAC. Calculate a SHA-256 HMAC of the rest of the decoded data using the decrypted encKey and compare it with the HMAC from the first 32 bytes.
- The next 16 bytes should be removed and used as the IV for the decryption algorithm.
- Decrypt the rest of the encPaymentData payload using AES-256-CBC, the IV from step 3, and the SHA256-hash of the decrypted encKey.
I tried using ColdFusion but I am lost somewhat with the encryption issues, and am unable to fix the code. Below I have what is required. I am stuck on the step 3 & 4 where they say compare it and then decrypt it. Can someone guide what could be done to fix it?
enckey:
2M2WWOD4wANsGwWTmPqQIQYdz9WPwgiR0ntJHGaxm23b5a1sWUtCBcUQUMMtc9hvcYavJ6yqPgETOGZgDOdd9qjDwIb2aV9DLZT1iIcB3zNN5Ddhxd9iiui6TAlJxU/O
encPaymentData:
X2TXp0ZmwHrtfzSP5TPjUOjdZb0rjsHeDSqr8TwIF/VR8sMQhWN5hP4IRhQxWT CZcQhxZoUHP 0g/E/ot sjREAJ8YQf7c7jSzKsXRH/wrew5rQit2wJBlVSSZ YoLeIHbLrTz CfIoFv09hixl7ff27u0YCyV0zjP5vNfCBEIwfqyriqwXK2J QEOxQiKzDUW4br3o1t31aymCQC9eBBpoVKjFfSKlNXM9QEdNZBcLMZ8Wlv8lF/ua bnwshbM9u7Uhudqvut94RZEW NzkRD8MfBo12e/XhnL35qxGpHeQNPClC4EQDK6U/HmegeOj BZLbIIYBs6t9E8Q3AKBwfiPOFgB gSVnhXKnd3nKvllaG BaGrQJtk 7QAtnHMHxQAO5rdiS9465HCdiHa8zlv7SkvWh8EwcKCiT4qiZSM6QuYAeRSzDpPS1gsZ54Q9LizUnueH7yyzSd47cLPd0VlOQxobKtNN2LrsRb3IwOfzuwGnSRf2cNp49hBmmGP1b0BC hhB6UpCqP2ixTPvui NwMYzqZUe336bF1mfnKzEbEZIvIrPyx3uMiLDAns2g7S80gMNnHb/09i49xbfY3V7oudeiHV99FCh67DuG3uHE3/HzIZbcnxJwVJoJj6/3DuzK/Kw1JqSorE0M1qxUqoNkJC4aNCBrqfTlR7/eErrvB554TUZwcyQXqKCwrKv4NJEw6S0n3W1VASkfA0atbJQX2aLgx9kqnhYdDbaU8UcFIoeA45 yEuQ9vXzo2ILQhvamsAAFQd3i4mEOZ KNtMu25dDFlORn5C/oTZ1t1dzJoYMvq44gejp6L3IK e7JCugGchr963a2kd8NFa3wctRDHF8ChHxawVlU0aY7nasrVireMFLiM 9XIb4abfDtct/j1Q8IGN0hRkgCHO6dlnOrAaaQDYYH3axaMDp5Onb04whULYqGbn/XSR8Sn8gnoFbYqVJbR5aCp5Pe9TpfwxlEvV3z8ZfsASqW2y So9gpwg2y16K/FX3Io6kqeqUlAxbTRDfN/ofDIJaO H PUu2teqjvwvCkjPciGOQdXT5JxqoCiHqRwD0zeZPcG3b9Nfrq3Caf6zjwhf /CMeGc3dNHhSkXox R50MP8BlLWk/bXZRScTE/HSrVxE n073utHAnbVOM3gVha0Hr8TmoV8z1vBg5fY253so6kQX61ZIfHneCAZo0qeKRgDgLUryVPmUNc5 yKP8DxtmHl/0YUztpgyEx5njsrn1L 3EHMMUhui8d LQdNZoEpZ9U1Xb7XVsV5gnwR/mOITNOKJQsine4zMMHBcomHclrM0CuI58YrKPqworCmK6CYfzSc8UmXxXUe5dzND/DS9XgqDttQic2/OqTSAK63ynnrNqzr3D56VpDBeDeQjk3mc/0zmuFAPEXoAQoQKfD6HEuajvWJebQ6QIPgA TshqsnPlktbpftr4lsuB1tHS/W8D7SYVFMC/Kxy9QuYWs0cmRTtzfWEKIRHeDElOTQCX5JB5PgzVhhi5kYTi488Ba8j4zvNUw55hEoMxONYO7eMjJosmNjULsT492LGw3EfAgmgx9h3yFLQRZgfylg0h4PfLlcPOAdsnVX9/yLElD xu7Atwc4S7pBWTHvwue7PpRvWpTeqkU5sqiX4KcV5x8rk mBtxm48a8fsmp GNf 4IjwXu9cQaU9WLipiEnkqFsYo7/aAsmmKWBETyQg9BFXYK 165vrzSX8WTsv6ZZDnVjcE1n4Ov8Jl2cnAigoQbB0ROPpIRzZ3zH2diUv1vzlSuh9gbEJf3uQRKlYRVUbpboC0RbQ/7jgznfJAWyLykyDQ0EB8fVEOtbP1l4JEz39QwAU18ph3btnWWuKEV4 ghYvNG4m1DYntSF57s2ajRS6rPtR oYvGjrJL9zbHBhKHlfkIPC0TKotOCi96mqpikbBEfIZSomHxYgDwYCSvt60zaDIjlBxZ1UBdK JL0554Wia9W3Wg91bmYS9Q4SXMT8r4xGYB7OutEV24n7p088rVm/w2SZSiqlLqai539k6WGkzEQf19ytPtIE81a N z7aijTjy 7FCuVPF90svI5/NoGpSINqv84HUcMU71BvXUIT53Ea6CCpiWvvOPpo/XZar44emlIG0UgeB kfP6C6sis=
Secret code:
zRf7WZ3nM7ON{U0E6J5S}KpVm@k2ReDyq#1lG9go
CF Code:
<cfset str = "2M2WWOD4wANsGwWTmPqQIQYdz9WPwgiR0ntJHGaxm23b5a1sWUtCBcUQUMMtc9hvcYavJ6yqPgETOGZgDOdd9qjDwIb2aV9DLZT1iIcB3zNN5Ddhxd9iiui6TAlJxU/O">
<cfset tobas = tobase64(str)>
<cfset getFirst32bytes = Left(tobas,32)>
<cfset tobas2 = RemoveChars(tobas,1,32)>
<cfdump var="#tobas2#">
<cfset key = "zRf7WZ3nM7ON{U0E6J5S}KpVm@k2ReDyq##1lG9go">
<cfset x = hmac("#tobas2#","#key#","HMACSHA256")>
<cfset y = hmac("#getFirst32bytes#","#key#","HMACSHA256")>
<cfset decalgo = Left(x,16)>
<cfset decremainingData = RemoveChars(x,1,16)>
<cfset getDec = Decrypt(decalgo,"#key#","AES")>
<cfdump var="#x#"><br>
<cfdump var="#y#"><br>
<cfdump var="#decalgo#">
<cfdump var="#decremainingData#">
<cfdump var="#getDec#">
This is the java example they have on their site:
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String HASH_ALGORITHM = "SHA-256";
private static final String HMAC_ALGORITHM = "HmacSHA256";
private static final int IV_LENGTH = 16, HMAC_LENGTH = 32;
private static final Charset utf8 = Charset.forName("UTF-8");
private static final Provider bcProvider;
static {
bcProvider = new BouncyCastleProvider();
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(bcProvider);
}
}
private static byte[] decrypt(byte[] key, byte[] data) throws GeneralSecurityException {
byte[] decodedData = Base64.decode(data);
if (decodedData == null || decodedData.length <= IV_LENGTH) {
throw new RuntimeException("Bad input data.");
}
byte[] hmac = new byte[HMAC_LENGTH];
System.arraycopy(decodedData, 0, hmac, 0, HMAC_LENGTH);
if (!Arrays.equals(hmac,
hmac(key, decodedData, HMAC_LENGTH, decodedData.length– HMAC_LENGTH))) {
throw new RuntimeException("HMAC validation failed.");
}
byte[] iv = new byte[IV_LENGTH];
System.arraycopy(decodedData, HMAC_LENGTH, iv, 0, IV_LENGTH);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, bcProvider);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(hash(key), "AES"),
new IvParameterSpec(iv));
return cipher.doFinal(decodedData, HMAC_LENGTH + IV_LENGTH,
decodedData.length– HMAC_LENGTH– IV_LENGTH);
}
private static byte[] hash(byte[] key) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(HASH_ALGORITHM);
md.update(key);
return md.digest();
}
private static byte[] hmac(byte[] key, byte[] data, int offset, int length)
throws GeneralSecurityException {
Mac mac = Mac.getInstance(HMAC_ALGORITHM, bcProvider);
mac.init(new SecretKeySpec(key, HMAC_ALGORITHM));
mac.update(data, offset, length);
return mac.doFinal();
}