Java

Sample Java code for XOR and encryption of the ecreq and ecres fields.

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Base64.getUrlDecoder;
import static java.util.Base64.getUrlEncoder;
import static javax.crypto.Cipher.DECRYPT_MODE;
import static javax.crypto.Cipher.ENCRYPT_MODE;

public class WebRedirection {
    private static final String AES_ALGO = "AES";
    private static final String KEY_ALGO = "PBKDF2WithHmacSHA256";
    private static final String AES_CBC_PKCS5 = "AES/CBC/PKCS5Padding";
    private static final String secretKey = "ac12ghd75kf75r";
    private static final String fi = "FIUID";

    public static String encrypt(String strToEncrypt, String salt) {
        final byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

        IvParameterSpec ivspec = new IvParameterSpec(iv);

        try {
            SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGO);
            KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
            SecretKey tmp = factory.generateSecret(spec);
            SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), AES_ALGO);
            Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5);
            cipher.init(ENCRYPT_MODE, secretKey, ivspec);
            return getUrlEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(UTF_8)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public static String decrypt(String strToDecrypt, String salt) {
        byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        IvParameterSpec ivspec = new IvParameterSpec(iv);
        try {
            SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGO);
            KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
            SecretKey tmp = factory.generateSecret(spec);
            SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), AES_ALGO);
            Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5);
            cipher.init(DECRYPT_MODE, secretKey, ivspec);
            return new String(cipher.doFinal(getUrlDecoder().decode(strToDecrypt)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void printUsage() {
        System.out.println("Usage: java EncryptUtil <salt> <payload>");
        System.out.println("       where, 'reqdate' is to be used as salt & payload is as per the webview URL redirection spec doc.");
        System.out.println("  e.g. java EncryptUtil 031120201803460 \"txnid=T1234&sessionid=S1234&srcref=Srcref1234&userid=acme@perfios-aa&redirect=https://example.com\"");
        System.out.println("");
    }

    public static void main(String[] args) {
        String salt = null;
        String payload = null;


        if (args.length < 2) {
            printUsage();
            return;
        }
        salt = args[0];
        payload = args[1];
        if (salt == null || salt.length() == 0) {
            System.out.println("Error: Salt must not be empty.");
            printUsage();
            return;
        } else {
            System.out.println("Using salt: " + salt);
        }
        if (payload == null || payload.length() == 0) {
            System.out.println("Error: Payload must not be empty.");
            printUsage();
            return;
        }
        System.out.println("Using payload: " + payload);
        String encData = encrypt(payload, salt);

        if (encData != null) {
            System.out.println("Encrypted & encoded data: " + encData);
            System.out.println("Decrypted data (to verify): " + decrypt(encData, salt));

            String xoredFI = encryptValueToXor(fi, salt);
            System.out.println("Xored FI: " + xoredFI);
            System.out.println("Xored FI (reversed): " + decryptXoredValue(xoredFI, salt));
        }
    }

    public static byte[] getRandomNonce(int numBytes) {
        byte[] nonce = new byte[numBytes];
        new SecureRandom().nextBytes(nonce);
        return nonce;
    }


    /**
     * Generate xored output of a using key.
     *
     * @param a
     * @param key
     * @return
     */
    static byte[] xor(byte[] a, byte[] key) {
        byte[] out = new byte[a.length];
        for (int i = 0; i < a.length; i++) {
            out[i] = (byte) (a[i] ^ key[i % key.length]);
        }
        return out;
    }

    static String decryptXoredValue(String xoredValue, String key) {
        return new String(xor(Base64.getDecoder().decode(xoredValue.getBytes()), key.getBytes()));
    }

    static String encryptValueToXor(String value, String key) {
        return new String(Base64.getEncoder().encode(xor(value.getBytes(), key.getBytes())));
    }
}

Last updated