---
# System prepended metadata

title: 設備生產_DAC_的流程 v2.1.0
tags: [Matter]

---

#### Version : v2.1.0

## 名詞定義

1. **Host** : 生產端
1. **Device** : 設備（例如 MS30N）
1. **hex string** : 0x11, 0x22, 0x33 會是 "112233" 用這樣表示
1. **DAC_package** : 包含 DAC、DAC 私鑰、DAC 公鑰、PAI 和 CD 的集合
    - 此部份的處理可以找 Ken
1. **Static_key** : Host 和 Device 需要事先知道此金鑰，用於保護 First_half_key/Second_half_key 的傳送
    - 使用 AES 256 ECB 的固定金鑰
    - 這裡的範例使用 : 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x30, 0x30, 0x39, 0x39, 0x38, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35, 0x35, 0x34, 0x34

1. **First_half_key** : Host 端所產出來的 Comm_key 前半段 key
    - 使用 AES 256 ECB
    - 前半段的 key 大小 16 bytes (請隨機產生)
    - 這裡的範例會使用 : 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x0a

1. **Second_half_key** : Host 端所產出來的 Comm_key 前半段 key
    - 使用 AES 256 ECB
    - 前半段的 key 大小 16 bytes (請隨機產生)
    - 這裡的範例會使用 : 0x72, 0x72, 0x74, 0x74, 0x79, 0x79, 0x75, 0x75, 0x69, 0x69, 0x6f, 0x6f, 0x70, 0x70, 0x6c, 0x6c, 0x0a

1. **Comm_key** : $First_half_key + $Second_half_key
    - 使用 AES 256 ECB

1. **Save_DAC_key** : 用於將從 Host 接收的 DAC 存儲到 Device 上的金鑰，用於對 DAC_package 進行加密後存檔
    - 此金鑰需要妥善保存(底下建議方法)
        - 使用分散存放
        - 使用部份演算
    - 使用 AES 256 CBC（key and iv）

## Linux command line tools

### AES ECB encryption

- echo -n "$(your text)" | openssl enc -e -aes-256-ecb -K $(key hex string) | base64 -w 0

```bash
# example
# data : "hello test"
# key (hex string) : "3131323233333434353536363737383839393030393938383737363635353434" 
$ echo -n "hello test" | openssl enc -e -aes-256-ecb -K "3131323233333434353536363737383839393030393938383737363635353434" | base64 -w 0
# output 
OxYybQGex3dzw3fG6dP3kg==
```

### AES ECB decryption

- echo "$(your encode base64 of decryptoing data)" | base64 -d | openssl enc -d -aes-256-ecb -K $(hex string key)

```bash
# example
# data : "OxYybQGex3dzw3fG6dP3kg=="
# key (hex string) : "3131323233333434353536363737383839393030393938383737363635353434" 
$ echo "OxYybQGex3dzw3fG6dP3kg==" | base64 -d | openssl enc -d -aes-256-ecb -K "3131323233333434353536363737383839393030393938383737363635353434"
# output 
hello test
```

## Host 和 Device 通訊方式

1. telnet
2. uart
3. tcp(telnet or tcp server client)

## 資料格式

- 使用 JSON

## 生產流程

### 1. 從WiSecKey取得DAC

```mermaid
sequenceDiagram
Host ->> DAC_server: 呼叫API(https://inesapi.certifyiddemo.com/v2/auth)請求本次交易token
DAC_server -->> Host: 回傳交易token
Host ->> DAC_server: 呼叫API(https://ines.certifyiddemo.com/admin/application)+交易token請求Access Keys
DAC_server -->> Host: 回傳Access Keys
Host ->> DAC_server: 呼叫API(https://inesapi.certifyid.com/v2/organizations/{organization_id}/certificates)+Access Keys + Device序號請求DAC\PAI封包
DAC_server -->> Host: 回傳以Device序號當作CN的加密DAC\PAI封包
Note left of Host: 解密DAC\PAI封包
Note right of Host: 製作成csv檔後，移交給生產程式

```

### 2. BL602燒入置換DAC韌體\MS30N燒入出廠韌體

### 3. 生產程式(Host)置換DAC
```mermaid
sequenceDiagram
Note left of Host: $Static_key(必須已存在)
Note right of Device: $Static_key(必須已存在)

Note left of Host: 將解密後的DAC\PAI封包拆解成 $DAC_package (註1)
Note left of Host: 產出 $First_half_key
Note left of Host: 使用 $Static_key 將 $First_half_key 進行加密<br> $Static_key($First_half_key)
Host->>Device: 傳送前半段金鑰 send $First_half_key (api:set_comm_key)
Note right of Device: 使用 $Static_key 解密取得 $First_half_key
Note right of Device: 產出 $Second_half_key
Note right of Device: 合併出 $Comm_key<br>$First_half_key + $Second_half_key
Note right of Device: 使用 $Static_key 將 $Second_half_key 進行加密<br> $Static_key($Second_half_key)
Device-->>Host: 回應加密後的 $Second_half_key

Note left of Host: 使用 $Static_key 解密並取得 $Second_half_key
Note over Host,Device: 合併出 $Comm_key<br>$First_half_key + $Second_half_key
Note left of Host: 使用 $Comm_key 對 $DAC_package 做加密(範例5)<br>$Comm_key($DAC_package)
Host->>Device: 傳送加密後的 $DAC_package (api:send_dac_package)
Note right of Device: 使用 $Comm_key 解密並取得 $DAC_package (範例6)
Note right of Device: 產生出 $Save_DAC_key
Note right of Device: 此步驟必定要執行<br>使用 $Save_DAC_key 對 $DAC_package 進行加密
Note right of Device: save $DAC_package

Device-->>Host: 回應成功 
```

### 4. BL602燒入燒入出廠韌體

## DAC寫入位置

|  | BL602 | MS30N |
| - | - | -|
| PAI\DAC | PSM(0x3C3000~3F6000) | /root/DAC.data|

---
---

# 註1 (將 DAC 相關資料拆解成 $DAC_package)

## 使用 WISeKey

## 自產 CD

- 因為還沒有取得認證所以需要自產
- 複製相關資料
    1. 建立測試資料夾
    1. 複製 connectedhomeip 提供的 CD pem and key
    1. 複製 chip-cert (請自行編譯出來)  

    ```bash
    mkdir test
    cp -a ~/linux_disk/amigo/open_source_project/connectedhomeip/credentials/test/certification-declaration/Chip-Test-CD-Signing-Key.pem ./
    cp -a ~/linux_disk/amigo/open_source_project/connectedhomeip/credentials/test/certification-declaration/Chip-Test-CD-Signing-Cert.pem ./
    cp -a ~/linux_disk/amigo/open_source_project/connectedhomeip/out/host/chip-cert ./
    ```

- setup 環境變數
    1. 設定你需要的 VID 和 VID
    1. 注意是 16 進制且不加 0x

    ```bash
    export VID=FFF1
    export PID=8189
    ```

- Generate CD
    1. 目前，將使用 chip-cert 生成 CD。目前，管理員只驗證 VID 和 PID 是否與設備其他地方公開的數據匹配：基本信息叢集、DAC 和 DAC 原始位置（若有）。您可以將其他字段保持不變。

    ```bash
    $ ./chip-cert gen-cd \
    --key ./Chip-Test-CD-Signing-Key.pem \
    --cert ./Chip-Test-CD-Signing-Cert.pem \
    --out ./Chip-Test-CD-${VID}-${PID}.der \
    --format-version "1" \
    --vendor-id "${VID}" \
    --product-id "${PID}" \
    --device-type-id "0x1234" \
    --certificate-id "ZIG20141ZB330001-24" \
    --security-level "0" \
    --security-info "0" \
    --version-number "9876" \
    --certification-type "0"
    ```

    1. Verify the CD. Make sure it contains your VID/PID (in decimal format):

    ```bash
    $ ./chip-cert print-cd ./Chip-Test-CD-${VID}-${PID}.der

    # output 
        SignerKeyId value: hex:62FA823359ACFAA9963E1CFA140ADDF504F37160
        0x01, tag[Anonymous]: 0x100, type: Structure (0x15), container: 
        0x04,     tag[Context Specific]: 0x0, type: Unsigned Fixed Point (0x04), value: 1
        0x08,     tag[Context Specific]: 0x1, type: Unsigned Fixed Point (0x04), value: 65521   # VID 0xFFF1
        0x0A,     tag[Context Specific]: 0x2, type: Array (0x16), container: 
        0x0D,         tag[Anonymous]: 0x100, type: Unsigned Fixed Point (0x04), value: 33161    # PID 0x8189
        0x12,     tag[Context Specific]: 0x3, type: Unsigned Fixed Point (0x04), value: 4660
        0x15,     tag[Context Specific]: 0x4, type: UTF-8 String (0x0c), length: 19, value: "ZIG20141ZB330001-24"
        0x2B,     tag[Context Specific]: 0x5, type: Unsigned Fixed Point (0x04), value: 0
        0x2E,     tag[Context Specific]: 0x6, type: Unsigned Fixed Point (0x04), value: 0
        0x32,     tag[Context Specific]: 0x7, type: Unsigned Fixed Point (0x04), value: 39030
        0x35,     tag[Context Specific]: 0x8, type: Unsigned Fixed Point (0x04), value: 0

    ```

    1. 產出 encode base64

    ```bash
    $ base64 -w 0 ./Chip-Test-CD-${VID}-${PID}.der
    # output
    MIHqBgkqhkiG9w0BBwKggdwwgdkCAQMxDTALBglghkgBZQMEAgEwRQYJKoZIhvcNAQcBoDgENhUkAAElAfH/NgIFiYEYJQM0EiwEE1pJRzIwMTQxWkIzMzAwMDEtMjQkBQAkBgAlB3aYJAgAGDF+MHwCAQOAFGL6gjNZrPqplj4c+hQK3fUE83FgMAsGCWCGSAFlAwQCATAKBggqhkjOPQQDAgRIMEYCIQDtIe2KMsYANYaUboMtzWEsY6NVFG0Z6xPWyXwp5gW3EwIhAI2NyBDByrxD2yH+KgTCjECe7cecm7cSt2OfVc4/FrWs
    ```

## 拆分檔案

1. 主要要使用 xxx_full.pem (04B0A0724FE75F1E_full.pem)
1. 將它拆分成四個檔案依序是, DAC private key, DAC, PAI ,PAA
1. 拆分檔案, 目前必要的是:
    - dac_key.pem 裡面的 private key
    - dac_key.pem 裡面的 publickey key
    - pai.pem
    - CD:
        - 當送驗 CSA 會簽發一個含有 VID and PID 的憑證,必須寫進產品內
        - 測試的時候需要自行產出並放入程式內編譯,請參閱 **"`自產 CD`"**

1. 測試必要檔案(正式站不需要)
    - paa.pem:
        - 當在配對的時候必須要此轉換成 .der 格式並放在 --paa-trust-store-path 能找的到的地方

```bash
# dac_key.pem
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILzEK1Wjjw7jR776IxdvH+kYbRu+ciOaYQBfVn5ZqROUoAoGCCqGSM49
AwEHoUQDQgAEzamLc8JTlxapTjoRg850BbPF/kbcuEeYxKhizyRmZWzOPjSZMIPb
D0qu8lB6Rdlg6AChDfH7/vsm36aeQGmLdQ==
-----END EC PRIVATE KEY-----


# dac.pem
-----BEGIN CERTIFICATE-----
MIIB2DCCAX+gAwIBAgIIAwfs1pB1A2owCgYIKoZIzj0EAwIwQDEoMCYGA1UEAwwf
TWF0dGVyIFBBSSBmb3IgQ29udG9zbyAyMDIzMDExNDEUMBIGCisGAQQBgqJ8AgEM
BEZGRjEwIBcNMjMxMDExMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMEExEzARBgNV
BAMMCktlbk1ha2VJdDIxFDASBgorBgEEAYKifAIBDARGRkYxMRQwEgYKKwYBBAGC
onwCAgwEODE4OTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABM2pi3PCU5cWqU46
EYPOdAWzxf5G3LhHmMSoYs8kZmVszj40mTCD2w9KrvJQekXZYOgAoQ3x+/77Jt+m
nkBpi3WjYDBeMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAURm9SgJWr3HuN7zS7
h+VZJIj2KP8wHQYDVR0OBBYEFM9DuuJe+DIviufCVsM8fr2QilugMA4GA1UdDwEB
/wQEAwIHgDAKBggqhkjOPQQDAgNHADBEAiAHFX1U2+nnRwSjsJBG1f1VouxSzlNz
0n82WghUWpsYEwIgMbTSuRO7ArxdGLPppH6UQg/vpv1RPFxH5e+KIyBQ8Yo=
-----END CERTIFICATE-----


# pai.pem
-----BEGIN CERTIFICATE-----
MIIB7zCCAZWgAwIBAgIIDyDSajmKu8AwCgYIKoZIzj0EAwIwUTELMAkGA1UEBhMC
Q0gxEDAOBgNVBAoMB1dJU2VLZXkxMDAuBgNVBAMMJ1dJU2VLZXkgUm9vdCBDQSBm
b3IgTWF0dGVyIFBLSSAyMDIzMDExNDAgFw0yMzAxMTUwMzAxMjBaGA85OTk5MTIz
MTIzNTk1OVowQDEoMCYGA1UEAwwfTWF0dGVyIFBBSSBmb3IgQ29udG9zbyAyMDIz
MDExNDEUMBIGCisGAQQBgqJ8AgEMBEZGRjEwWTATBgcqhkjOPQIBBggqhkjOPQMB
BwNCAASW04hStn+JHWagKgie9fKo6Sp9r0bnHAXBQVxzTmFQLG+T6rFTTugf1zfV
ybAU8WF5ACno9gVPz+iPfZqUYhPgo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMB8G
A1UdIwQYMBaAFKRdxF2nJYIxpngKmxG1pqQ6PwCYMB0GA1UdDgQWBBRGb1KAlavc
e43vNLuH5VkkiPYo/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwIDSAAwRQIh
AOm8awp7J3u70vc4jShCjbsIL/ySjGGgHVZXcA6ssnWzAiBUDvsVbaK3PZU9yFBJ
CjRHCvovL/oxUIr9lgJb2VzOmA==
-----END CERTIFICATE-----


# paa.pem
-----BEGIN CERTIFICATE-----
MIICADCCAaagAwIBAgIIT5Xdm374/9owCgYIKoZIzj0EAwIwUTELMAkGA1UEBhMC
Q0gxEDAOBgNVBAoMB1dJU2VLZXkxMDAuBgNVBAMMJ1dJU2VLZXkgUm9vdCBDQSBm
b3IgTWF0dGVyIFBLSSAyMDIzMDExNDAgFw0yMzAxMTUwMjU1NDlaGA85OTk5MTIz
MTIzNTk1OVowUTELMAkGA1UEBhMCQ0gxEDAOBgNVBAoMB1dJU2VLZXkxMDAuBgNV
BAMMJ1dJU2VLZXkgUm9vdCBDQSBmb3IgTWF0dGVyIFBLSSAyMDIzMDExNDBZMBMG
ByqGSM49AgEGCCqGSM49AwEHA0IABJ61RmP2dmdLPWiGS4YTa0JFRA1edqsfNV4K
xHM03quEPK6Pfa0uCvJb+HC/kIcZEDL76zrSjYL63puLKu1FHoqjZjBkMBIGA1Ud
EwEB/wQIMAYBAf8CAQEwHwYDVR0jBBgwFoAUpF3EXaclgjGmeAqbEbWmpDo/AJgw
HQYDVR0OBBYEFKRdxF2nJYIxpngKmxG1pqQ6PwCYMA4GA1UdDwEB/wQEAwIBBjAK
BggqhkjOPQQDAgNIADBFAiEA9jc0FmC4IXIdavi+67mHaBWSCqaXk0SpwYAZS4wH
sBkCIBxjEJ7fEmZt8USiGx2gABISyGU1GM6+GmugtW26xfLW
-----END CERTIFICATE-----
```

1. dac_key.pem 取得 dac private/public key 在個別轉換成 base64

- 看裡面的樣子

```bash
$ openssl ec -in dac_key.pem -noout -text
# output
read EC key
Private-Key: (256 bit)
priv:
    bc:c4:2b:55:a3:8f:0e:e3:47:be:fa:23:17:6f:1f:
    e9:18:6d:1b:be:72:23:9a:61:00:5f:56:7e:59:a9:
    13:94
pub:
    04:cd:a9:8b:73:c2:53:97:16:a9:4e:3a:11:83:ce:
    74:05:b3:c5:fe:46:dc:b8:47:98:c4:a8:62:cf:24:
    66:65:6c:ce:3e:34:99:30:83:db:0f:4a:ae:f2:50:
    7a:45:d9:60:e8:00:a1:0d:f1:fb:fe:fb:26:df:a6:
    9e:40:69:8b:75
ASN1 OID: prime256v1
NIST CURVE: P-256

private key (hexstring) : bcc42b55a38f0ee347befa23176f1fe9186d1bbe72239a61005f567e59a91394
public key (hexstring) : 04cda98b73c2539716a94e3a1183ce7405b3c5fe46dcb84798c4a862cf2466656cce3e34993083db0f4aaef2507a45d960e800a10df1fbfefb26dfa69e40698b75
```

- 取得 private base64

```bash
# private key encode base64
$ openssl ec -in dac_key.pem -noout -text > dac_key.txt
# 取得 private key 然後 encode base64
$ sed -n -e '/priv:/,/pub:/p' dac_key.txt | grep -v "priv:" | grep -v "pub:" | tr -d ' \n:' | sed 's/\(..\)/\1:/g; s/.$//' | xxd -r -p | base64 -w 0
# output 
vMQrVaOPDuNHvvojF28f6RhtG75yI5phAF9WflmpE5Q=
```

- 取得 public base64

```bash
# public key encode base64
$ openssl ec -in dac_key.pem -noout -text > dac_key.txt
# 取得 public key 然後 encode base64
$ sed -n -e '/pub:/,/ASN1 :/p' dac_key.txt | grep -v "pub:" | grep -v "ASN1 " | tr -d ' \n:' | sed 's/\(..\)/\1:/g; s/.$//' | xxd -r -p | base64 -w 0
# output 
BM2pi3PCU5cWqU46EYPOdAWzxf5G3LhHmMSoYs8kZmVszj40mTCD2w9KrvJQekXZYOgAoQ3x+/77Jt+mnkBpi3U=
```

- 驗證 (請和上面比對)

```bash
# private key
echo -e "vMQrVaOPDuNHvvojF28f6RhtG75yI5phAF9WflmpE5Q=" | base64 -d | xxd -p | tr -d '\n'
# output
bcc42b55a38f0ee347befa23176f1fe9186d1bbe72239a61005f567e59a91394


# public key
echo -e "BM2pi3PCU5cWqU46EYPOdAWzxf5G3LhHmMSoYs8kZmVszj40mTCD2w9KrvJQekXZYOgAoQ3x+/77Jt+mnkBpi3U=" | base64 -d | xxd -p | tr -d '\n'
# output
04cda98b73c2539716a94e3a1183ce7405b3c5fe46dcb84798c4a862cf2466656cce3e34993083db0f4aaef2507a45d960e800a10df1fbfefb26dfa69e40698b75
```

1. dac.pem to dac.der 在將其轉 enccode base64

```bash
$ openssl x509 -in ./dac.pem -outform DER | base64 -w 0
# output 
MIIB2DCCAX+gAwIBAgIIAwfs1pB1A2owCgYIKoZIzj0EAwIwQDEoMCYGA1UEAwwfTWF0dGVyIFBBSSBmb3IgQ29udG9zbyAyMDIzMDExNDEUMBIGCisGAQQBgqJ8AgEMBEZGRjEwIBcNMjMxMDExMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMEExEzARBgNVBAMMCktlbk1ha2VJdDIxFDASBgorBgEEAYKifAIBDARGRkYxMRQwEgYKKwYBBAGConwCAgwEODE4OTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABM2pi3PCU5cWqU46EYPOdAWzxf5G3LhHmMSoYs8kZmVszj40mTCD2w9KrvJQekXZYOgAoQ3x+/77Jt+mnkBpi3WjYDBeMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAURm9SgJWr3HuN7zS7h+VZJIj2KP8wHQYDVR0OBBYEFM9DuuJe+DIviufCVsM8fr2QilugMA4GA1UdDwEB/wQEAwIHgDAKBggqhkjOPQQDAgNHADBEAiAHFX1U2+nnRwSjsJBG1f1VouxSzlNz0n82WghUWpsYEwIgMbTSuRO7ArxdGLPppH6UQg/vpv1RPFxH5e+KIyBQ8Yo=
```

1. pai.pem to pai.der 在將其轉 enccode base64

```bash
$ openssl x509 -in ./pai.pem -outform DER | base64 -w 0
MIIB7zCCAZWgAwIBAgIIDyDSajmKu8AwCgYIKoZIzj0EAwIwUTELMAkGA1UEBhMCQ0gxEDAOBgNVBAoMB1dJU2VLZXkxMDAuBgNVBAMMJ1dJU2VLZXkgUm9vdCBDQSBmb3IgTWF0dGVyIFBLSSAyMDIzMDExNDAgFw0yMzAxMTUwMzAxMjBaGA85OTk5MTIzMTIzNTk1OVowQDEoMCYGA1UEAwwfTWF0dGVyIFBBSSBmb3IgQ29udG9zbyAyMDIzMDExNDEUMBIGCisGAQQBgqJ8AgEMBEZGRjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASW04hStn+JHWagKgie9fKo6Sp9r0bnHAXBQVxzTmFQLG+T6rFTTugf1zfVybAU8WF5ACno9gVPz+iPfZqUYhPgo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFKRdxF2nJYIxpngKmxG1pqQ6PwCYMB0GA1UdDgQWBBRGb1KAlavce43vNLuH5VkkiPYo/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwIDSAAwRQIhAOm8awp7J3u70vc4jShCjbsIL/ySjGGgHVZXcA6ssnWzAiBUDvsVbaK3PZU9yFBJCjRHCvovL/oxUIr9lgJb2VzOmA==
```

1. 在 Host 先將憑證都轉換成 `.der` 格式
   - 這部份可以找 Ken 詢問

1. 使用 JSON 格式，內部須包含 key
   - DAC
   - DAC_pub_key
   - DAC_pri_key
   - PAI
   - CD

   ```json
   {
       "DAC": "...",
       "DAC_pub_key": "...",
       "DAC_pri_key": "...",
       "PAI": "...",
       "CD": "..."
   }
   ```

1. Value use base64
1. 範例：

   ```JSON
    {
        "DAC": "MIIB2DCCAX+gAwIBAgIIAwfs1pB1A2owCgYIKoZIzj0EAwIwQDEoMCYGA1UEAwwfTWF0dGVyIFBBSSBmb3IgQ29udG9zbyAyMDIzMDExNDEUMBIGCisGAQQBgqJ8AgEMBEZGRjEwIBcNMjMxMDExMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMEExEzARBgNVBAMMCktlbk1ha2VJdDIxFDASBgorBgEEAYKifAIBDARGRkYxMRQwEgYKKwYBBAGConwCAgwEODE4OTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABM2pi3PCU5cWqU46EYPOdAWzxf5G3LhHmMSoYs8kZmVszj40mTCD2w9KrvJQekXZYOgAoQ3x+/77Jt+mnkBpi3WjYDBeMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAURm9SgJWr3HuN7zS7h+VZJIj2KP8wHQYDVR0OBBYEFM9DuuJe+DIviufCVsM8fr2QilugMA4GA1UdDwEB/wQEAwIHgDAKBggqhkjOPQQDAgNHADBEAiAHFX1U2+nnRwSjsJBG1f1VouxSzlNz0n82WghUWpsYEwIgMbTSuRO7ArxdGLPppH6UQg/vpv1RPFxH5e+KIyBQ8Yo=",
        "DAC_pub_key": "BM2pi3PCU5cWqU46EYPOdAWzxf5G3LhHmMSoYs8kZmVszj40mTCD2w9KrvJQekXZYOgAoQ3x+/77Jt+mnkBpi3U=",
        "DAC_pri_key": "04cda98b73c2539716a94e3a1183ce7405b3c5fe46dcb84798c4a862cf2466656cce3e34993083db0f4aaef2507a45d960e800a10df1fbfefb26dfa69e40698b75",
        "PAI":"MIIB7zCCAZWgAwIBAgIIDyDSajmKu8AwCgYIKoZIzj0EAwIwUTELMAkGA1UEBhMCQ0gxEDAOBgNVBAoMB1dJU2VLZXkxMDAuBgNVBAMMJ1dJU2VLZXkgUm9vdCBDQSBmb3IgTWF0dGVyIFBLSSAyMDIzMDExNDAgFw0yMzAxMTUwMzAxMjBaGA85OTk5MTIzMTIzNTk1OVowQDEoMCYGA1UEAwwfTWF0dGVyIFBBSSBmb3IgQ29udG9zbyAyMDIzMDExNDEUMBIGCisGAQQBgqJ8AgEMBEZGRjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASW04hStn+JHWagKgie9fKo6Sp9r0bnHAXBQVxzTmFQLG+T6rFTTugf1zfVybAU8WF5ACno9gVPz+iPfZqUYhPgo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFKRdxF2nJYIxpngKmxG1pqQ6PwCYMB0GA1UdDgQWBBRGb1KAlavce43vNLuH5VkkiPYo/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwIDSAAwRQIhAOm8awp7J3u70vc4jShCjbsIL/ySjGGgHVZXcA6ssnWzAiBUDvsVbaK3PZU9yFBJCjRHCvovL/oxUIr9lgJb2VzOmA==j",
        "CD": "MIHqBgkqhkiG9w0BBwKggdwwgdkCAQMxDTALBglghkgBZQMEAgEwRQYJKoZIhvcNAQcBoDgENhUkAAElAfH/NgIFiYEYJQM0EiwEE1pJRzIwMTQxWkIzMzAwMDEtMjQkBQAkBgAlB3aYJAgAGDF+MHwCAQOAFGL6gjNZrPqplj4c+hQK3fUE83FgMAsGCWCGSAFlAwQCATAKBggqhkjOPQQDAgRIMEYCIQDtIe2KMsYANYaUboMtzWEsY6NVFG0Z6xPWyXwp5gW3EwIhAI2NyBDByrxD2yH+KgTCjECe7cecm7cSt2OfVc4/FrWs"
    }

   ```

---
---

## API

### set_comm_key

- 設定並取得 Comm_key

1. request
    | key | value type | value        | required | descript      |
    |-----|------------|--------------|----------|---------------|
    | api | string     | set_comm_key |     Y    | const string  |
    | key | string     |              |     Y    | encode base64 |
    | sn  | string     |              |          |               |
    - key
        - Randomly generating
        - It's 16 bytes : 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x0a   # "aabbccddeeffgghh"
        - Encrypting using $Static_key with output in base64
    - sn : Marking the message of the request API

```JSON
{
    "api": "set_comm_key",
    "key": "hHX/CdUxj5Bp14YT9tVsSVgsj4IoqoSB5PeF7JdVk8g="
}
```

1. Response format
    | key      | value type | value        | required | descript                     |
    |----------|------------|--------------|----------|------------------------------|
    | api      | string     | set_comm_key |     Y    | const string                 |
    | ret_code | number     |              |     Y    | 0 is success, other is fail  |
    | msg      | string     |              |     Y    | detailed message of ret_code |
    | key      | string     |              |     Y    | encode base64                |
    | sn       | string     |              |          |                              |

    - key
        - Randomly generating
        - It's 16 bytes : 0x72, 0x72, 0x74, 0x74, 0x79, 0x79, 0x75, 0x75, 0x69, 0x69, 0x6f, 0x6f, 0x70, 0x70, 0x6c, 0x6c, 0x0a   # "rrttyyuuuuiioppll"
        - Encrypting using $Static_key with output in base64
    - sn : Response request sn's value

```JSON
{
  "api": "get_pub_key",
  "ret_code": 0,
  "msg": "success",
  "key": "yvlOWUaCsvF8bbrgGxHOvEB9aN4jDKFcftzD9ZIgAjY="
}
```

---

### send_dac_package

- 傳送加密後的 $DAC_package

1. request
    | key         | value type | value         | descript     |
    |-------------|------------|---------------|--------------|
    | api         | string     | send_dac_package | const string |
    | dac_package | string     |               | hex string   |

    - dac_package
        - 使用 $Comm_key 對 $DAC_package 進行加密,請參閱 (範例5)
        - $DAC_package 請參閱 (註1)

```JSON
{
    "api": "send_dac_package",
    "dac_package": 
    "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"
}
```

1. Response format
    | key      | value type | value       | descript                            |
    |----------|------------|-------------|-------------------------------------|
    | ret_code | number     | 0           | 0 表示成功, 其餘皆為失敗,可參閱 msg 欄位 |
    | msg      | string     | success     | success 表示成功其餘街失敗內容          |

```JSON
{
  "api": "send_comm_key",
  "ret_code": 0,
  "msg": "success",
}
```

# AES c

## Encryptor

- encryptor.c
- build : gcc encryptor.c -o encryptor -lssl -lcrypto

```c
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>

int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *ciphertext)
{
    if (!plaintext || plaintext_len <= 0 || !key || !ciphertext)
        return -1;

    EVP_CIPHER_CTX *ctx = NULL;
    int len = 0;
    int ciphertext_len = 0;

    if (!(ctx = EVP_CIPHER_CTX_new()))
    {
        ciphertext_len = -2;
        goto err;
    }

    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
    {
        ciphertext_len = -3;
        goto err;
    }

    if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
    {
        ciphertext_len = -4;
        goto err;
    }

    ciphertext_len = len;

    if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
    {
        ciphertext_len = -5;
        goto err;
    }

    ciphertext_len += len;

err:
    EVP_CIPHER_CTX_free(ctx);

    return ciphertext_len;
}

int base64_encode(const unsigned char *input, int length, char *out, int out_len)
{
    if (!input || length < 0 || !out || out_len < 0)
        return -1;

    memset(out, 0, out_len);
    BIO *bio = NULL;
    BIO *b64 = NULL;
    FILE *stream;
    int encoded_size = 4 * ((length + 2) / 3);

    if (out_len < encoded_size)
        return -2;
    int ret = 0;
    stream = fmemopen(out, encoded_size + 1, "w");
    if (!stream)
    {
        ret = -3;
        goto err;
    }
    b64 = BIO_new(BIO_f_base64());
    if (!b64)
    {
        ret = -4;
        goto err;
    }
    bio = BIO_new_fp(stream, BIO_NOCLOSE);
    if (!bio)
    {
        ret = -5;
        goto err;
    }
    if (!BIO_push(b64, bio))
    {
        ret = -6;
        goto err;
    }
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    if (0 > BIO_write(b64, input, length))
    {
        ret = -7;
        goto err;
    }
    BIO_flush(b64);

err:

    BIO_free_all(b64);
    fclose(stream);
    return 0;
}

int main(void)
{
    char *plaintext = "{\"DAC\":\"MIIB2DCCAX+gAwIBAgIIAwfs1pB1A2owCgYIKoZIzj0EAwIwQDEoMCYGA1UEAwwfTWF0dGVyIFBBSSBmb3IgQ29udG9zbyAyMDIzMDExNDEUMBIGCisGAQQBgqJ8AgEMBEZGRjEwIBcNMjMxMDExMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMEExEzARBgNVBAMMCktlbk1ha2VJdDIxFDASBgorBgEEAYKifAIBDARGRkYxMRQwEgYKKwYBBAGConwCAgwEODE4OTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABM2pi3PCU5cWqU46EYPOdAWzxf5G3LhHmMSoYs8kZmVszj40mTCD2w9KrvJQekXZYOgAoQ3x+/77Jt+mnkBpi3WjYDBeMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAURm9SgJWr3HuN7zS7h+VZJIj2KP8wHQYDVR0OBBYEFM9DuuJe+DIviufCVsM8fr2QilugMA4GA1UdDwEB/wQEAwIHgDAKBggqhkjOPQQDAgNHADBEAiAHFX1U2+nnRwSjsJBG1f1VouxSzlNz0n82WghUWpsYEwIgMbTSuRO7ArxdGLPppH6UQg/vpv1RPFxH5e+KIyBQ8Yo=\",\"DAC_pub_key\":\"BM2pi3PCU5cWqU46EYPOdAWzxf5G3LhHmMSoYs8kZmVszj40mTCD2w9KrvJQekXZYOgAoQ3x+/77Jt+mnkBpi3U=\",\"DAC_pri_key\":\"04cda98b73c2539716a94e3a1183ce7405b3c5fe46dcb84798c4a862cf2466656cce3e34993083db0f4aaef2507a45d960e800a10df1fbfefb26dfa69e40698b75\",\"PAI\":\"MIIB7zCCAZWgAwIBAgIIDyDSajmKu8AwCgYIKoZIzj0EAwIwUTELMAkGA1UEBhMCQ0gxEDAOBgNVBAoMB1dJU2VLZXkxMDAuBgNVBAMMJ1dJU2VLZXkgUm9vdCBDQSBmb3IgTWF0dGVyIFBLSSAyMDIzMDExNDAgFw0yMzAxMTUwMzAxMjBaGA85OTk5MTIzMTIzNTk1OVowQDEoMCYGA1UEAwwfTWF0dGVyIFBBSSBmb3IgQ29udG9zbyAyMDIzMDExNDEUMBIGCisGAQQBgqJ8AgEMBEZGRjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASW04hStn+JHWagKgie9fKo6Sp9r0bnHAXBQVxzTmFQLG+T6rFTTugf1zfVybAU8WF5ACno9gVPz+iPfZqUYhPgo2YwZDASBgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFKRdxF2nJYIxpngKmxG1pqQ6PwCYMB0GA1UdDgQWBBRGb1KAlavce43vNLuH5VkkiPYo/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwIDSAAwRQIhAOm8awp7J3u70vc4jShCjbsIL/ySjGGgHVZXcA6ssnWzAiBUDvsVbaK3PZU9yFBJCjRHCvovL/oxUIr9lgJb2VzOmA==j\",\"CD\":\"MIHqBgkqhkiG9w0BBwKggdwwgdkCAQMxDTALBglghkgBZQMEAgEwRQYJKoZIhvcNAQcBoDgENhUkAAElAfH/NgIFiYEYJQM0EiwEE1pJRzIwMTQxWkIzMzAwMDEtMjQkBQAkBgAlB3aYJAgAGDF+MHwCAQOAFGL6gjNZrPqplj4c+hQK3fUE83FgMAsGCWCGSAFlAwQCATAKBggqhkjOPQQDAgRIMEYCIQDtIe2KMsYANYaUboMtzWEsY6NVFG0Z6xPWyXwp5gW3EwIhAI2NyBDByrxD2yH+KgTCjECe7cecm7cSt2OfVc4/FrWs\"}";
    int plaintext_len = strlen(plaintext);

    // hexstring "3131323233333434353536363737383839393030393938383737363635353434"
    unsigned char key[] = {0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x30, 0x30, 0x39, 0x39, 0x38, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35, 0x35, 0x34, 0x34};
    int cipher_buf_len = ((plaintext_len + 15) / 16) * 16; // Adjusting the buffer size for the ciphertext
    unsigned char ciphertext[cipher_buf_len];
    memset(ciphertext, 0, cipher_buf_len);

    int ciphertext_len = aes_encrypt((unsigned char *)plaintext, plaintext_len, key, ciphertext);
    if (ciphertext_len < 0)
    {
        printf("Error aes encrypto fail:%d\n", ciphertext_len);
        return 1;
    }
    int encoded_size = 4 * ((ciphertext_len + 2) / 3);
    char base64_output[encoded_size];
    memset(base64_output, 0, encoded_size);

    int ret = base64_encode(ciphertext, ciphertext_len, base64_output, encoded_size);
    if (ret < 0)
    {
        printf("base64_encode error:%d\n", ret);
        return 2;
    }
    printf("%s\n", base64_output);
    return 0;
}
```

## Decryptor

- encryptor.c
- build : gcc decryptor.c -o decryptor -lssl -lcrypto

```c
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *plaintext)
{
    if (!ciphertext || ciphertext_len <= 0 || !key || !plaintext)
        return -1;

    EVP_CIPHER_CTX *ctx = NULL;
    int len = 0;
    int plaintext_len = 0;

    if (!(ctx = EVP_CIPHER_CTX_new()))
    {
        plaintext_len = -2;
        goto err;
    }

    if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
    {
        plaintext_len = -3;
        goto err;
    }

    if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
    {
        plaintext_len = -4;
        goto err;
    }

    plaintext_len = len;

    if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
    {
        plaintext_len = -5;
        goto err;
    }

    plaintext_len += len;

err:
    EVP_CIPHER_CTX_free(ctx);

    return plaintext_len;
}

int base64_decode(const char *input, unsigned char *output, int out_len)
{
    if (!input || !output || out_len < 0)
        return -1;

    BIO *bio = NULL;
    BIO *b64 = NULL;
    int decoded_size = strlen(input) * 3 / 4;
    int ret = 0;
    bio = BIO_new_mem_buf((void *)input, -1);
    if (!bio)
    {
        ret = -2;
        goto err;
    }
    b64 = BIO_new(BIO_f_base64());
    if (!b64)
    {
        ret = -3;
        goto err;
    }
    bio = BIO_push(b64, bio);
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
    int len = BIO_read(bio, output, strlen(input));
    if (len < 0)
    {
        ret = -4;
        goto err;
    }

    ret = len;

err:
    BIO_free_all(b64);
    return ret;
}

int main(void)
{
    char *base64_ciphertext = "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";
    unsigned char key[] = {0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x30, 0x30, 0x39, 0x39, 0x38, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35, 0x35, 0x34, 0x34};
    int encoded_size = strlen(base64_ciphertext);
    unsigned char ciphertext[encoded_size];
    memset(ciphertext, 0, encoded_size);

    int ciphertext_len = base64_decode(base64_ciphertext, ciphertext, encoded_size);
    if (ciphertext_len < 0)
    {
        printf("Base64 decode error:%d\n", ciphertext_len);
        return 1;
    }

    int plain_buf_len = ciphertext_len;
    unsigned char plaintext[plain_buf_len + 1];
    memset(plaintext, 0, sizeof(plaintext));

    int plaintext_len = aes_decrypt(ciphertext, ciphertext_len, key, plaintext);
    if (plaintext_len < 0)
    {
        printf("AES decrypt error:%d\n", plaintext_len);
        return 2;
    }
    printf("%s\n", plaintext);
    return 0;
}

```
