# Yêu cầu bảo mật

### Kênh truyền SSL/HTTPS <a href="#kenh-truyen-sslhttps" id="kenh-truyen-sslhttps"></a>

SSL/HTTPS được áp dụng để truyền nhận dữ liệu giữa hệ thống của đối tác và Gotadi. Mục đích sử dụng SSL/HTTPS là giúp dữ liệu trao đổi giữa đối tác và Gotadi được mã hóa, khó bị đánh cắp và giả mạo.

### Header bảo mật và thống kê lưu lượng truyền <a href="#header-bao-mat-va-thong-ke-luu-luong-truyen" id="header-bao-mat-va-thong-ke-luu-luong-truyen"></a>

Tất cả các request từ phía đối tác gọi sang hệ thống của Gotadi phải chứa các Headers bên dưới để phục vụ các nghiệp vụ về bảo mật và thống kê số liệu của Gotadi:

```
apikey: <api_key>
x-ibe-req-name: <access_code>
```

Lưu ý

Giá trị `<api_key>` và `<access_code>` do Gotadi cung cấp cho Đối tác.

### Mã hóa dữ liệu truyền và xác thực chữ ký điện tử <a href="#ma-hoa-du-lieu-truyen-va-xac-thuc-chu-ky-ien-tu" id="ma-hoa-du-lieu-truyen-va-xac-thuc-chu-ky-ien-tu"></a>

Request/response giữa Gotadi và Đối tác ở một số API quan trọng được yêu cầu mã hóa bằng thuật toán mã hóa bất đối xứng 3DES và kèm theo chữ ký điện tử để xác thực. Thuật toán mã hóa, giải mã sẽ được mô tả cụ thể trong tài liệu này.

Lưu ý

Các API có yêu cầu mã hóa dữ liệu và kèm theo chữ ký điện tử sẽ được ghi chú ở phần Yêu cầu bảo mật.

#### Mã hóa dữ liệu gửi đi <a href="#ma-hoa-du-lieu-gui-i" id="ma-hoa-du-lieu-gui-i"></a>

* **Input** Original data, RSA PublicKey của bên nhận, RSA Private Key của bên gửi
* **Output** Encrypted Key, Encrypted Data

<details>

<summary>Bước 1: Khởi tạo khóa ngẫu nhiên (Random key)</summary>

![](https://3127657987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fka3LMTlXv2Ay7BbFZMOc%2Fuploads%2FWEQ4EdiuUC733f6YD56a%2FScreenshot%202023-06-01%20at%2010.36.30.png?alt=media\&token=a71853a4-fe83-47d0-a4d0-1ea4ad9eb7a6)

Hàm 3DES Key Generate được dùng để tạo random key dựa theo tiêu chí DESedeKeySpec (Độ dài key: 24 byte). Mỗi request/response sẽ được cấp một random key riêng biệt.

#### Example:

```javascript
    public static byte[] generateKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
        SecretKey secretKey = keyGenerator.generateKey();
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
        DESedeKeySpec deSedeKeySpec = (DESedeKeySpec)   secretKeyFactory.getKeySpec(secretKey, DESedeKeySpec.class);
        byte[] randomKey = deSedeKeySpec.getKey();
        return randomKey;
    }
```

</details>

<details>

<summary>Bước 2: Mã hóa khóa ngẫu nhiên (Encrypted random key)</summary>

![](https://3127657987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fka3LMTlXv2Ay7BbFZMOc%2Fuploads%2FQ6RJFSab1qsmugeuemVy%2FScreenshot%202023-06-01%20at%2010.37.22.png?alt=media\&token=4fd522b6-3772-40e7-86f1-8e6e997ef64d)

Random key được tạo ra ở bước 1 sẽ được mã hóa bằng thuật toán mã hóa bất đối xứng RSA bằng **Public key của bên nhận**.

#### Example:

```javascript
public static String encryptRSA(byte[] randomKey, String xmlPublicKey) throws Exception {
    Cipher cipher = createCipherEncrypt(xmlPublicKey);
    byte[] encryptedKey = cipher.doFinal(randomKey);
    return Base64.encodeBase64URLSafeString(encryptedKey);
}
```

</details>

<details>

<summary>Bước 3: Khởi tạo chữ ký chữ ký điện tử (Signature)</summary>

![](https://3127657987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fka3LMTlXv2Ay7BbFZMOc%2Fuploads%2FBuNudRgyItys0LdOZEpc%2FScreenshot%202023-06-01%20at%2010.38.45.png?alt=media\&token=5beab99c-f4c7-416c-9ff8-ae0726017cc2)

Bên gửi áp dụng thuật toán **RSA-SHA256** kết hợp với **Private key của chính mình** để ký chữ ký điện tử trên signature data.

Lưu ý

Schema để thành lập signature data sẽ được mô tả cụ thể ở từng API.

#### Example:

```java
public static String signRSA(String signatureData, String xmlPrivateKey) throws Exception {
    PrivateKey privateKey = getPrivateKeyFromXML(xmlPrivateKey);
    Signature instance = Signature.getInstance("SHA256withRSA");
    instance.initSign(privateKey);
    instance.update(signatureData.getBytes("UTF-8"));
    byte[] signature = instance.sign();
    return Base64.encodeBase64String(signature);
}
```

</details>

<details>

<summary>Bước 4: Mã hóa dữ liệu (Encrypted data)</summary>

![](https://3127657987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fka3LMTlXv2Ay7BbFZMOc%2Fuploads%2F2KfvCCCna2kf1hyj3JJ1%2FScreenshot%202023-06-01%20at%2010.39.47.png?alt=media\&token=04885eca-fee2-4b11-91df-f1317d532f1a)

**Original data có chứa signature** sẽ được mã hóa bằng thuật toán **3DES** với random key đã được tạo ra ở bước trước đó.

Lưu ý

Schema để thành lập original data sẽ được mô tả cụ thể ở từng API.

#### Example:

```javascript
public static String encryptTripleDes(String originalData, byte[] randomKey) throws Exception {
    Cipher cipher = Cipher.getInstance("DESede");
    SecretKeySpec secretKeySpec = new SecretKeySpec(randomKey, "DESede");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    byte[] encryptedData = cipher.doFinal(originalData.getBytes("UTF-8"));
    return Base64.encodeBase64URLSafeString(encryptedData);
}
```

</details>

#### Giải mã dữ liệu nhận được và xác thực chữ ký điện tử <a href="#giai-ma-du-lieu-nhan-uoc-va-xac-thuc-chu-ky-ien-tu" id="giai-ma-du-lieu-nhan-uoc-va-xac-thuc-chu-ky-ien-tu"></a>

* **Input** Encrypted Key, Encrypted Data, RSA PrivateKey của bên nhận, RSA PublicKey của bên gửi
* **Output** Original Data, Verify Result

<details>

<summary>Bước 1: Giải mã khóa ngẫu nhiên 3DES (Decrypted random key)</summary>

![](https://3127657987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fka3LMTlXv2Ay7BbFZMOc%2Fuploads%2F7mUENQUXQvuwj4NlH6hP%2FScreenshot%202023-06-01%20at%2010.40.11.png?alt=media\&token=d85840f9-c698-4fe8-9048-c66de121d9ac)

Bên nhận sử dụng **Private key của chính mình** để giải mã encrypted key nhận được.

#### Example:

```java
public static byte[] decryptRSAToByte(String encryptedKey, String xmlPrivateKey) throws Exception {
    Cipher cipher = createCipherDecrypt(xmlPrivateKey);
    byte[] bts = Base64.decodeBase64(encryptedKey);
    byte[] randomKey = cipher.doFinal(bts);
    return randomKey;
}
```

</details>

<details>

<summary>Bước 2: Giải mã dữ liệu (Decrypted data)</summary>

![](https://3127657987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fka3LMTlXv2Ay7BbFZMOc%2Fuploads%2FtT8SrV6hUFBFy1SnsNkh%2FScreenshot%202023-06-01%20at%2010.40.32.png?alt=media\&token=ddddf553-0d45-4cc6-9c4d-6398315bf5ba)

Bên nhận áp dụng thuật toán **3DES** kết hợp với random key có được ở bước trước đó, giải mã encrypted data để nhận được **original data có chứa signature**.

Lưu ý

Schema để thành lập original data sẽ được mô tả cụ thể ở từng API.

#### Example:

```java
public static String decryptTripleDes(String encryptedData, byte[] randomKey) throws Exception {
    Cipher cipher = Cipher.getInstance("DESede");
    SecretKeySpec secretKeySpec = new SecretKeySpec(randomKey, "DESede");
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    byte[] originalData  = cipher.doFinal(Base64.decodeBase64(encryptedData));
    return new String(originalData, "UTF-8");
}
```

</details>

<details>

<summary>Bước 3: Xác thực chữ ký điện tử</summary>

![](https://3127657987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fka3LMTlXv2Ay7BbFZMOc%2Fuploads%2FTnlPIVK5IbuOzWSSG72n%2FScreenshot%202023-06-01%20at%2010.40.47.png?alt=media\&token=a05efd6b-2910-4c76-852e-62d0e131e760)

Bên nhận sử dụng Thuật toán **RSA-SHA256 và Public key của bên gửi** để xác thực signature được lấy ra từ original data.

#### Example:

```java
public static boolean verifyRSA(String signedData, String signature, String xmlPublicKey) throws Exception {
    PublicKey publicKey = getPublicKeyFromXML(xmlPublicKey);
    Signature instance = Signature.getInstance("SHA256withRSA");
    instance.initVerify(publicKey);
    instance.update(signedData.getBytes("UTF-8"));
    return instance.verify(Base64.decodeBase64(signature));
}
```

</details>

<br>
