java - recibir - visa checkout peru
Descifrar los datos de pago con Visa Checkout (1)
Una cosa importante de entender sobre el código de muestra es que se refiere a bytes . Su código CF está usando caracteres. Puede parecer una distinción trivial, pero son cosas totalmente diferentes, que producirán resultados muy, muy diferentes. Para descifrar correctamente, debe trabajar con los bytes (o binarios) de las cadenas dadas, no con caracteres.
Aunque es posible manipular matrices binarias utilizando funciones CF centrales, como arraySlice () , la sintaxis se vuelve un poco abultada / torpe a veces. La razón es que las matrices binarias son un tipo diferente de objeto que su matriz CF estándar, es decir, byte [] versus java.util.List . Entonces, dependiendo de qué funciones se usen, es posible que necesite javacast para forzar las variables en el tipo esperado. Con eso en mente ..
Parte I - Descifra el encKey
- Base64-decodifica la encKey.
- Elimine los primeros 32 bytes del valor decodificado. Este es el HMAC (Código de Autenticación de Mensaje Hash). Calcule un HMAC SHA-256 del resto de los datos decodificados utilizando su secreto compartido API y compárelo con el HMAC de los primeros 32 bytes.
Primero convierta la cadena base64 en binario usando binaryDecode . A continuación, extraiga la cantidad adecuada de bytes de la matriz devuelta. Este es el valor de HMAC esperado :
hmacSize = 32;
binaryToDecrypt = binaryDecode(encryptedKey, "base64");
expectedHMAC = binaryEncode( javacast("byte[]", arraySlice(binaryToDecrypt, 1, hmacSize))
, "hex" );
A continuación, extraiga todos los bytes restantes y úselos para calcular el HMAC real. Verifíquelo contra el valor esperado. Si los dos no coinciden, algo salió mal.
remainData = arraySlice(binaryToDecrypt, hmacSize + 1);
actualHMAC = hmac( javacast("byte[]", remainData ), sharedSecret, "HMACSHA256");
if (compare(actualHMAC, expectedHMAC) != 0) {
throw("ERROR: Invalid HMAC ["& actualHMAC &"]. Expected ["& expectedHMAC &"]");
}
- Los siguientes 16 bytes deben eliminarse y utilizarse como IV (Vector de inicialización) para el algoritmo de descifrado.
Los bytes restantes contienen un IV, seguido del valor encriptado. Antes de que puedas descifrar el último, debes extraer y separar los dos:
ivSize = 16;
ivValue = javacast("byte[]", arraySlice(remainData, 1, ivSize));
encryptedValue = javacast("byte[]", arraySlice(remainData, ivSize + 1));
- Descifre los datos restantes utilizando AES-256-CBC, el IV del paso 3 y el hash SHA-256 de su API Shared Secret.
El último paso antes de poder descifrar es generar la clave de descifrado, al calcular el secreto compartido. Desafortunadamente, la función hash () de CF siempre devuelve una cadena hexadecimal. Por lo tanto, se debe convertir a formato base64 para que sea compatible con la función de descifrado.
keyHex = hash(sharedSecret, "SHA-256", "utf-8");
keyBase64 = binaryEncode(binaryDecode(keyHex, "hex"), "base64");
Finalmente, use los tres valores para descifrar. El binario devuelto contendrá la clave de cifrado utilizada en la parte II.
decryptedKeyBinary = decryptBinary( encryptedValue
, keyBase64
, "AES/CBC/PKCS5Padding"
, ivValue);
Parte II - Descifra el encPaymentData
Use el mismo proceso exacto que en la Parte I, simplemente cambie las variables:
- Utilice
encPaymentData
lugar deencryptedKey
- Utilice
sharedSecret
lugar desharedSecret
.
El resultado final descifrado será binario. Use charsetEncode para convertirlo nuevamente en una cadena legible para el ser humano:
result = charsetEncode(decryptedResult, "utf-8");
NB: Los valores de muestra que publicó parecen estar rotos, ya que ni siquiera funcionan con el ejemplo de Java. Los pasos anteriores producen el resultado correcto cuando se usan valores válidos (clave, datos, etc.).
Estoy recuperando información de Visa Checkout en un formato encriptado. La guía en su sitio proporciona estas instrucciones:
En primer lugar, debe descifrar la clave dinámica (encKey) y luego usar el valor de la clave dinámica desencriptada para descifrar la carga útil de datos de pago (encPaymentData).
Siga estos cuatro pasos para descifrar encKey:
- Base64-decodifica la encKey.
- Elimine los primeros 32 bytes del valor decodificado. Este es el HMAC (Código de Autenticación de Mensaje Hash). Calcule un SHA-256 HMAC de
resto de los datos decodificados usando su API Shared Secret y compararlo
al HMAC desde los primeros 32 bytes.- Los siguientes 16 bytes deben eliminarse y utilizarse como IV (Vector de inicialización) para el algoritmo de descifrado.
- Descifre los datos restantes usando AES-256-CBC, el IV del paso 3 y el hash SHA-256 de su API Shared Secret.
Siga estos cuatro pasos para descifrar encPaymentData utilizando la encKey descifrada:
- Base64: decodifica encPaymentData.
- Elimine los primeros 32 bytes del valor decodificado. Este es el HMAC. Calcule un SHA-256 HMAC del resto de los datos decodificados utilizando la encKey desencriptada y compárela con el HMAC de los primeros 32 bytes.
- Los siguientes 16 bytes se deben eliminar y usar como IV para el algoritmo de descifrado.
- Desencripte el resto de la carga útil encPaymentData utilizando AES-256-CBC, el IV del paso 3 y el hash SHA256 de la encKey descifrada.
Intenté usar ColdFusion pero estoy algo perdido con los problemas de encriptación y no puedo arreglar el código. A continuación tengo lo que se requiere. Estoy atrapado en el paso 3 y 4 donde dicen que lo comparan y luego lo descifran. ¿Alguien puede guiar lo que podría hacerse para solucionarlo?
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=
Código secreto:
zRf7WZ3nM7ON{U0E6J5S}KpVm@k2ReDyq#1lG9go
Código CF:
<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#">
Este es el ejemplo de Java que tienen en su sitio:
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();
}