# Security

### Request Signature

**1、Request header**

| Name                                           | Type   | Description                      |
| ---------------------------------------------- | ------ | -------------------------------- |
| Content-Type<mark style="color:red;">\*</mark> | string | application/json; chartset=UTF-8 |

**2、Request body**

<pre class="language-javascript" data-full-width="false"><code class="lang-javascript"><strong>{
</strong>    "app_id": "2017051914172236111",
    "partner_id": "000000000000001",
    "timestamp": "2011-09-23 04:24:03",
    "version": "1.0",
    "request_id": "bO8lENHnboElE",
    "sign_type": "RSA",
    "random_key": "OvUp0Z7zhLfYdBR1lOKLfYdBR1lOKLfYdBR1lOK", //need to be encrypted
    "biz_data": "Z7zhLfYdBR1lOKLfYdBR7zhLfYdBR1lOKLfYdBR" //need to be encrypted
}
</code></pre>

**3、Signature**

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

{% hint style="info" %}
Pagsmile RSA public key is available in your app’s configuration of the **Pagsmile Dashboard**.
{% endhint %}

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

### Response Signature

**1、Response body**

{% code fullWidth="false" %}

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

{% endcode %}

**2、Signature**

`random_key:` Decrypt using the **Merchant RSA private key**.

{% hint style="info" %}
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.**
{% endhint %}

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

### Example &#x20;

{% tabs %}
{% tab title="JAVA" %}

<pre><code><strong>
</strong>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 &#x3C; bytes.length; j++) {
            int v = bytes[j] &#x26; 0xFF;
            hexChars[j * 2] = HEX_ARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEX_ARRAY[v &#x26; 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);
    }
}
</code></pre>

{% endtab %}

{% tab title="PHP" %}
**Encryption algorithm in PHP-**&#x65;ncrypt with RSA Public Key

```
<?php

// public key
$publicKey = 'public key';

function encryptSecret(string $secret, string $publicKey): string
{

    openssl_public_encrypt($secret, $encryptedData, $publicKey, OPENSSL_PKCS1_PADDING);

    return base64_encode($encryptedData);
}

function encryptContent(string $content, string $secret): string
{
    $iv = bin2hex(random_bytes(8));
    $encryptedData = openssl_encrypt($content, 'aes-256-cbc', $secret, OPENSSL_RAW_DATA, $iv);

    return $iv.base64_encode($encryptedData);
}

// usage
$secret = 'RandomString32CharactersLength12'; // 32 characters; must be randomly generated for every response 
$random_key = encryptSecret($secret, $publicKey); // add to 'random_key'
$biz_data = '{"responseCode":"00","billingAmount":"11186","holderAmount":"11186","availableBalance":100008814,"settledBalance":100020000}';
$encryptedContent = encryptContent($content, $secret); // set this to be the response body

// Optional outputs that show the result
echo $sign.PHP_EOL;
echo $encryptedContent.PHP_EOL;
```

**Decryption algorithm in PHP**

```
<?php

// Client private key
$privateKey = 'insert your private key here';
$encryptedContent = 'raw response body'; // Get from the webhook body

function decryptSecret(string $sign, string $privateKey): string
{

    openssl_private_decrypt(base64_decode($sign), $secret, $privateKey, OPENSSL_PKCS1_PADDING);

    return $secret;
}

function decryptContent(string $encryptedContent, string $secret): string
{
    $iv = substr($encryptedContent, 0, 16);
    $encryptedData = base64_decode(substr($encryptedContent, 16));

    return openssl_decrypt($encryptedData, 'aes-256-cbc', $secret, OPENSSL_RAW_DATA, $iv);
}

// usage
$decryptedSecret = decryptSecret($sign, $privateKey);
$decryptedContent = decryptContent($encryptedContent, $decryptedSecret);

// Optional output that shows the result
echo $decryptedContent.PHP_EOL;
```

{% endtab %}

{% tab title="C#" %}
**Encryption algorithm in C# (encrypt with RSA public key)**

```

// ISAC public key
string publicKey = "insert ISAC public key here";

static string EncryptSecret(string secret, string publicKey)
{
    var encryptEngine = new Pkcs1Encoding(new RsaEngine());
    using (var reader = new StringReader(publicKey))
    {
        encryptEngine.Init(true, (AsymmetricKeyParameter)new PemReader(reader).ReadObject());
    }

    var data = Encoding.UTF8.GetBytes(secret);
    var encryptedData = encryptEngine.ProcessBlock(data, 0, data.Length);

    return Convert.ToBase64String(encryptedData);
}

static string EncryptContent(string content, string secret)
{
    var iv = Hex.Encode(new SecureRandom().GenerateSeed(8));

    var cipher = CipherUtilities.GetCipher("AES/CBC/PKCS7PADDING");
    var keyParam = new KeyParameter(Encoding.UTF8.GetBytes(secret));
    var keyParamWithIv = new ParametersWithIV(keyParam, iv, 0, 16);
    cipher.Init(true, keyParamWithIv);

    var encryptedData = cipher.DoFinal(Encoding.UTF8.GetBytes(content));

    return Encoding.UTF8.GetString(iv) + Convert.ToBase64String(encryptedData);
}

string secret = "RandomString32CharactersLength12"; // 32 characters; must be randomly generated for every response
string sign = EncryptSecret(secret, publicKey); //
string bizData = "{"responseCode":"00","billingAmount":"11186","holderAmount":"11186","availableBalance":100008814,"settledBalance":100020000}";
string encryptedContent = EncryptContent(content, secret); // set this to be the response body
// Optional outputs that show the result
Console.WriteLine(sign);
Console.WriteLine(encryptedContent);

```

**Decryption algorithm in C#**&#x20;

```

// Client private key
string privateKey = "Client private key";

string sign = "response"; // Get from response 'random_Key'
string encryptedContent = "raw response body"; // Get from Get from response 'data'

static string DecryptSecret(string sign, string privateKey)
{
    var encryptEngine = new Pkcs1Encoding(new RsaEngine());
    using (var reader = new StringReader(privateKey))
    {
        decryptEngine.Init(false, (AsymmetricKeyParameter)new PemReader(reader).ReadObject());
    }

    var data = Convert.FromBase64String(sign);
    var decryptedData = decryptEngine.ProcessBlock(data, 0, data.Length);

    return Encoding.UTF8.GetString(decryptedData);
}

static string DecryptContent(string encryptedContent, string secret)
{
    var iv = Encoding.UTF8.GetBytes(encryptedContent.Substring(0, 16));
    var encryptedData = Convert.FromBase64String(encryptedContent.Substring(16));

    var cipher = CipherUtilities.GetCipher("AES/CBC/PKCS7PADDING");
    var keyParam = new KeyParameter(Encoding.UTF8.GetBytes(secret));
    var keyParamWithIv = new ParametersWithIV(keyParam, iv, 0, 16);
    cipher.Init(false, keyParamWithIv);

    var data = cipher.DoFinal(encryptedData);

    return Encoding.UTF8.GetString(data);
}

// usage
string decryptedSecret = DecryptSecret(sign, privateKey);
string decryptedContent = DecryptContent(encryptedContent, decryptedSecret);

// Optional output that shows the result
Console.WriteLine(decryptedContent);
```

<br>
{% endtab %}

{% tab title="NodeJs" %}
**Encryption algorithm in Node.js (encrypt with RSA public key)**

```
// Import necessary modules
const crypto = require('crypto');

// ISAC public key
const publicKey = `insert public key here`;

function encryptSecret(secret, publicKey) {
    const encryptedData = crypto.publicEncrypt({
        key: publicKey,
        padding: crypto.constants.RSA_PKCS1_PADDING
    }, Buffer.from(secret));

    return encryptedData.toString('base64');
}

function encryptContent(content, secret) {
    const iv = crypto.randomBytes(8).toString('hex');
    const cipher = crypto.createCipheriv('aes-256-cbc', secret, iv);

    let encryptedData = cipher.update(content, 'utf8', 'base64');
    encryptedData += cipher.final('base64');

    return iv + encryptedData;
}
// usage
const secret = 'RandomString32CharactersLength12'; // 32 characters; must be randomly generated for every response to a webhook
const sign = encryptSecret(secret, publicKey); // add to 'random_key'
const content = `{"responseCode":"00","billingAmount":"11186","holderAmount":"11186","availableBalance":100008814,"settledBalance":100020000}`;
const encryptedContent = encryptContent(content, secret); //  add to 'biz_data'

console.log(sign);
console.log(encryptedContent);
```

**Decryption algorithm in Node.js**&#x20;

```
// Import necessary modules
const crypto = require('crypto');

//  private key
const publicKey = `insert your private key here`;
const sign = ``; // Get from response as 'random_key'
const encryptedContent = `raw response body`; // Get from response as 'data'

function decryptSecret(sign, privateKey) {
    const decryptedData = crypto.privateDecrypt({
        key: privateKey,
        padding: crypto.constants.RSA_PKCS1_PADDING
    }, Buffer.from(sign, 'base64'));

    return decryptedData.toString();
}

function decryptContent(encryptedContent, secret) {
    const iv = encryptedContent.slice(0, 16);
    const encryptedData = Buffer.from(encryptedContent.slice(16), 'base64');

    const decipher = crypto.createDecipheriv('aes-256-cbc', secret, iv);
    decipher.setAutoPadding(false);
    let decryptedData = decipher.update(encryptedData);
    decryptedData = Buffer.concat([decryptedData, decipher.final()]);

    return decryptedData.toString();
}
// usage
decryptedSecret = decryptSecret(sign, privateKey);
decryptedContent = decryptContent(encryptedContent, decryptedSecret);
console.log(decryptedContent);
```

<br>
{% endtab %}

{% tab title="Python" %}
**Encryption algorithm Python (encrypt with RSA public key)**

```
def encrypt_secret(public_key_pem: str, secret: str) -> str:

    rsa_key = RSA.import_key(public_key_pem)

    cipher = PKCS1_v1_5.new(rsa_key)
    encrypted_sign = cipher.encrypt(secret.encode('utf-8'))

    return base64.b64encode(encrypted_sign).decode('utf-8')


def encrypt_content(content, secret):
    iv = os.urandom(8).hex()

    cipher = AES.new(secret.encode(), AES.MODE_CBC, iv.encode())
    encrypted_data = cipher.encrypt(pad(content.encode(), AES.block_size))

    return iv + base64.b64encode(encrypted_data).decode()
   
 
def decrypt_secret(sign, private_key):
    private_key = PKCS1_v1_5.new(RSA.import_key(private_key))

    return private_key.decrypt(base64.b64decode(sign)).decode()

def decrypt_content(encrypted_content, secret):
    iv = encrypted_content[:16]
    encrypted_data = base64.b64decode(encrypted_content[16:])

    cipher = AES.new(secret.encode(), AES.MODE_CBC, iv.encode())
    data = unpad(cipher.decrypt(encrypted_data), AES.block_size)

    return data.decode()
```

{% endtab %}
{% endtabs %}

### &#x20;        &#x20;

```
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pagsmile.com/issuing-card-api/security.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
