#### 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; } ```