Security

Pagsmile uses hybrid encryption (AES + RSA) for secure communication.

Request Signature

1、Request header

Name
Type
Description

Content-Type*

string

application/json; chartset=UTF-8

2、Request body

{
    "app_id": "2017051914172236111",
    "partner_id": "000000000000001",
    "sub_partner_id": "",
    "timestamp": "2011-09-23 04:24:03",
    "version": "1.0",
    "random_key": "OvUp0Z7zhLfYdBR1lOK", //need to be encrypted
    "request_id": "jJT3+PR9CSowcR2QOK5OzMjVmTSjGoectzYbO8lENHnboElE",
    "sign_type": "RSA",
    "biz_data": {}. //need to be encrypted
}

3、Signature

randomKey: A randomly generated 16-byte AES key, encrypted with Pagsmile RSA public key (2048-bit).

Pagsmile RSA public key is available in your app’s configuration of the Pagsmile Dashboard.

biz_Data: Encrypted data, secured with the randomly generated AES key.

Response Signature

1、Response body

{
    "code": "10000",
    "msg": "Success",
    "data": { }, //need to be decrypted
    "total":1
    "random_key":"OvUp0Z7zhLfYdBR1lOK/F1fE0jKGiwsIea9XD9urkav",//need to be decrypted
    "sign_type": "RSA",
    "app_id": "2017051914172236111"
}

2、Signature

random_key: Decrypt using the Merchant RSA private key.

The response is encrypted with your Merchant RSA Public Key. Please ensure that you have updated the Merchant RSA Public Key in your app’s configuration of the Pagsmile Dashboard.

data: Use the decrypted AES key to decode the message content.

Example


public class CryptoUtil {
    private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
    public static IvParameterSpec generateIvValue() {
        return new IvParameterSpec(generateRandom16Chars().getBytes());
    }
    private static String generateRandom16Chars() {
        byte[] array = new byte[8];
        SecureRandom random = new SecureRandom();
        random.nextBytes(array);
        return bytesToHex(array);
    }
    private static String bytesToHex(byte[] bytes) {
        byte[] hexChars = new byte[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars, StandardCharsets.UTF_8);
    }
}

public class CryptoExample {

    //encrypt random_key
    public static String encryptSecret(PublicKey publicKey, String secret) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // PKCS1 or OAEP padding "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" can be used
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedSign = cipher.doFinal(secret.getBytes());
        return Base64.getEncoder().encodeToString(encryptedSign);
    }
    //encrypt biz_data
    public static String encryptContentMode(String content, String secret) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        IvParameterSpec iv = CryptoUtil.generateIvValue();
        SecretKey secretKey = new SecretKeySpec(secret.getBytes(), "AES");
        Cipher dataCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        dataCipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        byte[] encryptedDataBytes = dataCipher.doFinal(content.getBytes());
        return new String(iv.getIV()) + Base64.getEncoder().encodeToString(encryptedDataBytes);
    }
    //decrypt random_key
    public static String decryptSecretMode(PrivateKey privateKey, String sign) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        byte[] encryptedDataBytes = Base64.getDecoder().decode(sign);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // PKCS1 or OAEP padding "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" can be used
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] secretByte = cipher.doFinal(encryptedDataBytes);
        return new String(secretByte);
    }
    //decrypt data
    public static String decryptContentMode(String encryptedContent, String secret) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        String ivString = encryptedContent.substring(0, 16);
        String correctEncryptedData = encryptedContent.substring(16);
        byte[] encryptedDataBytes = Base64.getDecoder().decode(correctEncryptedData);
        IvParameterSpec iv = new IvParameterSpec(ivString.getBytes());
        SecretKey secretKey = new SecretKeySpec(secret.getBytes(), "AES");
        Cipher dataCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        dataCipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
        byte[] decryptedDataBytes = dataCipher.doFinal(encryptedDataBytes);
        return new String(decryptedDataBytes);
    }
}

Last updated

Was this helpful?