日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

Paho-MQTT C使用ID2-KM接入阿里云物聯網平臺

本文介紹了開源Paho MQTT embeded-c如何通過更安全的身份認證方式(ID2)連接到阿里云物聯網平臺,并建立安全傳輸通道。

1. 術語

  1. Soft-KM(Key Management)密鑰管理,由阿里提供的軟件安全沙箱,基于軟件加固和虛擬化技術提供對密鑰(IoT ID2)的安全保護。

  2. OSA(Operation System Abstractor Layer)操作系統抽象層,定義內存申請和釋放、日志打印、系統時間、網絡通信等接口,非遵循POSIX標準的OS,需重新適配這些接口。

  3. HAL(Hardware Abstractor Layer)硬件抽象層,根據設備硬件特性,完成對加解密算法、設備唯一ID、密鑰管理和數據安全存儲的接口適配。

  4. ID2 OTP(One-Time Provisioning)一次性燒錄,也稱ID2空發,指設備在第一次聯網時,通過網絡請求,下發ID2數據燒錄到設備中。

  5. TLS(Transport Layer Security)安全傳輸層協議, 用于兩個通信實體之間,保護通信數據的私密性和完整性。

  6. IoT(Internet of things)物聯網,基于互聯網實現萬物互聯。

  7. 阿里云物聯網平臺(Link Platform)阿里云物聯網平臺,提供物聯網的設備管理。

?

2. ID2產品架構

  1. ID2控制中心:

  • ID2的Web控制臺,提供對ID2產線灌裝、ID2產品和配額申請、以及ID2使用統計的管理。

  1. ID2服務中心:

  • ID2在云端的應用,提供ID2的各種安全能力,包括ID2密鑰安全分發、設備認證、基于ID2的安全連接協議等;同時,提供各種能力的云端接口,支持業務平臺的二次開發,支持不同的安全業務需求和場景。

  1. ID2 Client SDK:

  • ID2在設備端的功能組件和軟件開發框架,可支持不同操作系統和不同硬件,為IoT設備提供基于ID2的端到端的設備認證、數據加解密等各種安全能力。

?

3. ID2接入流程

3.1 概述:

  • 阿里云物聯網平臺接入的方式,ID2已默認同物聯網平臺打通,因此不需要進行服務端對接。

  • 設備建連的過程,IoT設備通過Paho MQTT Client SDK調用ID2-iTLS,進行設備認證和會話密鑰協商,最后建立數據安全傳輸通道。

  • 設備建連成功后,IoT設備和物聯網平臺,通過安全通道進行應用數據的安全傳輸。

?

  • ID2對接步驟如下:

3.2 創建產品:

  1. 登錄物聯網平臺控制臺

  2. 點擊選擇的實例,在左側導航欄,選擇設備管理 > 產品,單擊創建產品:

  1. 填寫產品信息,認證方式選擇ID2:

3.3 購買ID2:

  1. 購買ID2認證授權:

image.png

  1. 分配ID2認證授權:

2.1 登錄到ID2控制臺,進入入門指引 - IoT設備身份認證頁面,選擇“與阿里云物聯網平臺組合使用”,點擊“開始接入”。

2.2 在“配置產品“步驟中,“選擇產品”,然后“分配ID2授權數量”。

3.4 設備端對接:

3.4.1 ID2 SDK框架:

image.png

  1. IoT Application:

  • 設備端的應用程序,負責業務數據處理,包括設備認證、設備建連和數據收發等。

  1. Paho MQTT Client SDK:

  • Eclipse Paho MQTT C/C++ Client開源代碼實現,提供基于MQTT協議的數據管理。

  1. ID2 Client SDK:

  • iTLS:輕量的安全連接協議TLS,基于ID2完成TLS的握手認證和密鑰協議,提供應用數據的收發。

  • ID2:IoT設備認證的對外接口,上層應用/協議基于此接口進行開發。

  • KM:密鑰管理模塊,支持不同形式的載體:

  • Soft-KM:軟件沙箱,基于軟件加固和虛擬化技術提供對ID2密鑰的安全保護。

  • SE:安全芯片,基于物理防護機制,提供對ID2密鑰的安全保護,通過AT指令對設備提供ID2的運算。

  • Crypto:提供統一的加解密算法接口。

  • OSA:操作系統適配接口,廠商需根據使用的OS,重新進行接口適配。

  • HAL:硬件適配接口,提供算法庫和Soft-KM的適配接口,廠商需根據選擇的硬件平臺,重新進行接口適配。

3.4.2 ID2 設備端SDK獲取:

  1. ID2 設備端 SDK下載:

  1. ID2 Release Package目錄:

目錄/文件

說明

app

測試用例,包括HAL和ID2

include

頭文件

libs

ID2模塊的靜態庫

makefile

編譯腳本

make.rules

編譯系統配置文件,可配置編譯工具鏈和編譯參數

sample

ID2的示例代碼

src

需適配的OSA和HAL接口和參考實現

3.4.3 ID2 設備端SDK對接:

  1. 設備端適配:

根據選擇的OS和硬件平臺,完成ID2 SDK的移植。

?

  • 基于ID2 Release Package進行移植,OSA和HAL需要廠商根據接口說明進行重新適配。

  • 第一步:OSA接口適配:

  • 實現src/osa/ls_osa.c中的接口:

  • 已提供Linux系統的參考實現可只實現其中的基礎接口和網絡接口。

  • 第二步:HAL接口適配:

  • 實現src/hal/km/demo/ls_hal_km.c中的接口:

  • 已提供Linux系統的參考實現:

  • 單獨預留的KM安全分區大于2K, 且需保證在系統升級和重啟時,分區數據不被破壞。

  • ls_hal_get_id接口,需使用設備硬件唯一標識。

  • 第三步:HAL接口測試:

  • 修改makefile.rules的編譯配置文件:

  • 配置目標平臺(pLat := xxx)。

  • CROSS_COMPILE設置對應的編譯工具鏈。

  • CFLAGS設置編譯的配置參數。

  • 執行編譯"make clean & make"。

  • 正確運行程序hal_test,可得到如下成功日志:

  • "HAL Key Management Test Pass"。

  1. 設備端集成:

Paho MQTT調用設備端ID2的接口,完成相應的設備認證、數據加密等安全功能。

說明

下文通過在Linux系統,演示如何集成和使能ID2的認證和數據加密能力

  • 第二步:MQTT集成ID2的安全通道:

  1. MQTTClient-C/src目錄,在Linux下創建libs,拷貝已適配好的ID2靜態庫和頭文件。

  2. linux/MQTTLinux.h - 更新Network結構體和接口

typedef struct Network
{
        char *product_key;
        char *product_secret;
        uintptr_t handle;
        int (*mqttread) (struct Network*, unsigned char*, int, int);
        int (*mqttwrite) (struct Network*, unsigned char*, int, int);
} Network;

int mqtt_itls_read(Network*, unsigned char*, int, int);
int mqtt_itls_write(Network*, unsigned char*, int, int);

DLLExport void NetworkSetConfig(Network *, char *, char *);
DLLExport void NetworkInit(Network*);
DLLExport int NetworkConnect(Network*, char*, int);
DLLExport void NetworkDisconnect(Network*);
  • Network結構體:

  • 增加product_key成員:阿里云物聯網平臺(LP)- 產品標識

  • 增加product_secret成員:阿里云物聯網平臺(LP)- 產品密鑰

  • 變更網絡句柄類型:my_socket(int) -> handle(uintptr_t)

  • Network網絡接口:

  • 增加NetworkSetConfig:用于配置LP產品標識和產品密鑰

  1. linux/MQTTLinux.c - 適配Network網絡接口:

#include "hal_itls.h"

int mqtt_itls_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
    return hal_itls_read(n->handle, buffer, len, timeout_ms);
}

int mqtt_itls_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
{
    return hal_itls_write(n->handle, buffer, len, timeout_ms);
}

void NetworkSetConfig(Network* n, char *product_key, char *product_secret)
{
    n->product_key = product_key;
    n->product_secret = product_secret;
}

void NetworkInit(Network* n)
{
    n->handle = 0;
    n->mqttread = mqtt_itls_read;
    n->mqttwrite = mqtt_itls_write;
}

int NetworkConnect(Network* n, char* addr, int port)
{
    n->handle = hal_itls_establish(addr, port, n->product_key, n->product_secret);
    if (n->handle == 0) {
        return -1;
    }

    return 0;
}

void NetworkDisconnect(Network* n)
{
    hal_itls_destroy(n->handle);
}

  1. CMakeLists.txt - 鏈接ID2靜態庫:

file(GLOB SOURCES "*.c" "linux/*.c")

add_library(
  paho-embed-mqtt3cc SHARED
  ${SOURCES}
)
install(TARGETS paho-embed-mqtt3cc DESTINATION /usr/lib)

add_library(libitls STATIC IMPORTED)
set_target_properties(libitls PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/linux/libs/libitls.a)
add_library(libid2 STATIC IMPORTED)
set_target_properties(libid2 PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/linux/libs/libid2.a)
add_library(libicrypt STATIC IMPORTED)
set_target_properties(libicrypt PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/linux/libs/libicrypt.a)
add_library(libkm STATIC IMPORTED)
set_target_properties(libkm PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/linux/libs/libkm.a)
add_library(libls_hal STATIC IMPORTED)
set_target_properties(libls_hal PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/linux/libs/libls_hal.a)
add_library(libls_osa STATIC IMPORTED)
set_target_properties(libls_osa PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/linux/libs/libls_osa.a)

target_link_libraries(paho-embed-mqtt3cc libitls libid2 libicrypt libkm libls_hal libls_osa)
target_link_libraries(paho-embed-mqtt3cc rt pthread)

target_include_directories(paho-embed-mqtt3cc PRIVATE "linux" "linux/include/itls")
target_link_libraries(paho-embed-mqtt3cc paho-embed-mqtt3c)
target_compile_definitions(paho-embed-mqtt3cc PRIVATE
             MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h MQTTCLIENT_QOS2=1)

  • 第三步:Paho通過ID2連接LP的示例 - MQTTClient-C/samples:

  1. linux/aiot_id2_demo.c示例代碼:

#include "MQTTClient.h"

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>

#define EXAMPLE_PRODUCT_KEY         "xxxxxxx"
#define EXAMPLE_PRODUCT_SECRET      "xxxxxxx"
#define EXAMPLE_DEVICE_NAME         "Paho_ID2_Device_1"
#define EXAMPLE_DEVICE_SECRET       "b21bc6147266242838d06ff50c00d0ab"

#if !defined(CONFIG_LP_INSTANCED)
#define MQTT_CLINETID_KV            "|securemode=8,signmethod=hmacsha1,timestamp=2524608000000,authtype=id2|"
#else
#define MQTT_CLINETID_KV            "|securemode=8,signmethod=hmacsha1,timestamp=2524608000000,authtype=id2,instanceId=xxxxx|"
#endif

#define PRODUCTKEY_MAXLEN           (20)
#define DEVICENAME_MAXLEN           (32)
#define DEVICESECRET_MAXLEN         (64)

#define USERNAME_MAXLEN             (64)
#define PASSWORD_MAXLEN             (65)

int aiotMqttSign(const char *productKey, const char *deviceName, const char *deviceSecret, 
                     char clientId[150], char username[64], char password[65])
{
    char deviceId[PRODUCTKEY_MAXLEN + DEVICENAME_MAXLEN + 2] = {0};

    /* setup deviceId */
    memcpy(deviceId, deviceName, strlen(deviceName));
    memcpy(deviceId + strlen(deviceId), "&", strlen("&"));
    memcpy(deviceId + strlen(deviceId), productKey, strlen(productKey));

    /* setup clientid */
    memcpy(clientId, deviceId, strlen(deviceId));
    memcpy(clientId + strlen(deviceId), MQTT_CLINETID_KV, strlen(MQTT_CLINETID_KV));
    memset(clientId + strlen(deviceId) + strlen(MQTT_CLINETID_KV), 0, 1);

    /* setup username */
    memcpy(username, deviceId, strlen(deviceId));
    memset(username + strlen(deviceId), 0, 1);

    /* setup password */
    memset(password, '0', PASSWORD_MAXLEN - 1);
    memcpy(password, "FFFFFFFFFFFFFFFF1234567812345678", 32);

    return 0;
}

volatile int toStop = 0;

void cfinish(int sig)
{
    signal(SIGINT, NULL);
    toStop = 1;
}

void messageArrived(MessageData* md)
{
    MQTTMessage* message = md->message;

    printf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);
    printf("%.*s\n", (int)message->payloadlen, (char*)message->payload);
}

/* main function */
int main(int argc, char** argv)
{
    int rc = 0;

    /* setup the buffer, it must big enough for aliyun IoT platform */
    unsigned char buf[1000];
    unsigned char readbuf[1000];

    Network n;
    MQTTClient c;
    char *host = EXAMPLE_PRODUCT_KEY".itls.cn-shanghai.aliyuncs.com";
    short port = 1883;

    const char *subTopic = "/"EXAMPLE_PRODUCT_KEY"/"EXAMPLE_DEVICE_NAME"/user/get";
    const char *pubTopic = "/"EXAMPLE_PRODUCT_KEY"/"EXAMPLE_DEVICE_NAME"/user/update";

    /* invoke aiotMqttSign to generate mqtt connect parameters */
    char clientId[150] = {0};
    char username[65] = {0};
    char password[65] = {0};

    if ((rc = aiotMqttSign(EXAMPLE_PRODUCT_KEY, EXAMPLE_DEVICE_NAME,
                           EXAMPLE_DEVICE_SECRET, clientId, username, password) < 0)) {
        printf("aiotMqttSign -%0x4x\n", -rc);
        return -1;
    }

    printf("clientid: %s\n", clientId);
    printf("username: %s\n", username);
    printf("password: %s\n", password);

    signal(SIGINT, cfinish);
    signal(SIGTERM, cfinish);

    /* network init and establish network to aliyun IoT platform */
    NetworkInit(&n);
    NetworkSetConfig(&n, EXAMPLE_PRODUCT_KEY, EXAMPLE_PRODUCT_SECRET);
    rc = NetworkConnect(&n, host, port);
    if (rc < 0) {
        printf("NetworkConnect %d\n", rc);
        return -1;
    }

    /* init mqtt client */
    MQTTClientInit(&c, &n, 1000, buf, sizeof(buf), readbuf, sizeof(readbuf));
 
    /* set the default message handler */
    c.defaultMessageHandler = messageArrived;

    /* set mqtt connect parameter */
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = clientId;
    data.username.cstring = username;
    data.password.cstring = password;
    data.keepAliveInterval = 60;
    data.cleansession = 1;
    printf("Connecting to %s %d\n", host, port);

    rc = MQTTConnect(&c, &data);
    if (rc < 0) {
        printf("MQTTConnect fail %d!\n", rc);
        return -1;
    } else {
        printf("MQTTConnect %d, Connect aliyun IoT Cloud Success!\n", rc);
    }    

    printf("Subscribing to %s\n", subTopic);
    rc = MQTTSubscribe(&c, subTopic, 1, messageArrived);
    printf("MQTTSubscribe %d\n", rc);

    int cnt = 0;
    unsigned int msgid = 0;
    while (!toStop)
    {
        MQTTYield(&c, 1000);	

        if (++cnt % 5 == 0) {
            MQTTMessage msg = {
                                QOS1, 0, 0, 0, "Hello world", strlen("Hello world"),
                              };
            msg.id = ++msgid;
            rc = MQTTPublish(&c, pubTopic, &msg);
            printf("MQTTPublish %d, msgid %d\n", rc, msgid);
        }
    }

    printf("Stopping\n");

    MQTTDisconnect(&c);
    NetworkDisconnect(&n);

    return 0;
}
  • 更新如下的信息:

  • EXAMPLE_PRODUCT_KEY:填寫阿里云物聯網平臺(LP)產品標識,在創建時需選擇“ID2認證”

  • EXAMPLE_PRODUCT_SECRET:填寫阿里云物聯網平臺(LP)產品密鑰,在產品創建控制臺查詢

  • EXAMPLE_DEVICE_NAME:填寫設備標識,產品維度內唯一

  • EXAMPLE_DEVICE_SECRET:填寫設備密鑰,選擇“ID2認證”時,可以使用任意字符串

  • 選擇正確的MQTT_CLINETID_KV:ClientId的鍵值信息

  • LP公共實例:

  • deviceId+"|securemode=8,signmethod=hmacsha1,timestamp=2524608000000,authtype=id2|"

  • LP企業實例:

  • "|securemode=8,signmethod=hmacsha1,timestamp=2524608000000,authtype=id2,instanceId=xxxxx|", 其中instanceId為企業實例ID(登錄物聯網平臺控制臺,在實例概覽頁面查看)

  • LP平臺的域名和端口號:

  • host:${YourProductKey}.itls.cn-shanghai.aliyuncs.com,其中${YourProductKey}為申請的產品標識

  • port:1883

  1. CMakeLists.txt - 編譯腳本:

add_executable(
  stdoutsubc
  stdoutsub.c
)

target_link_libraries(stdoutsubc paho-embed-mqtt3cc paho-embed-mqtt3c)
target_include_directories(stdoutsubc PRIVATE "../../src" "../../src/linux")
target_compile_definitions(stdoutsubc PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h)

add_executable(
  aiot_id2_demo
  aiot_id2_demo.c
)

target_link_libraries(aiot_id2_demo paho-embed-mqtt3cc paho-embed-mqtt3c)
target_include_directories(aiot_id2_demo PRIVATE "../../src" "../../src/linux" "./include/osa")
target_compile_definitions(aiot_id2_demo PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h)

  • 第四步:固件編譯:

  • paho.mqtt.embedded-c根目錄,創建build.paho編譯目錄

  • 到build.paho目錄,運行"cmake & make"進行編譯

  • 編譯成功,ID2固件生成在build.paho/MQTTClient-C/samples/linux目錄

  • 第五步:固件運行:

  • 正確運行aiot_id2_demo,可得到如下日志:

image.png

3.5 調試驗證:

  1. ID2建連錯誤調試:

  • ID2-iTLS建連失敗時,首先可以通過查看消息警告(alert message)進行問題排查:

image.png

  • 上面的消息警告中,2 - FATAL類型的警告;172 - 消息警告類型,ID2-iTLS常見的錯誤警告類型如下:

錯誤碼

錯誤信息

評論

160

ID2 generic error

通用錯誤,檢查Product Secret是否正確

161

ID2 no quota

ID2配額不足,需先購買ID2

162

ID2 is not exist

服務端識別不了此ID2,可刪除設備上ID2(如KM載體)后,重新空發ID2

163

ID2 authcode is invalid

ID2認證碼錯誤,校驗挑戰字是否有效(ID2服務端申請&只使用一次)

164

ID2 has not been activated

ID2已經激活

165

The timestamp used in authcode is expired

檢查設備端時間是否同步

166

ID2 challenge is invalid

ID2認證碼中,挑戰字非法(挑戰字模式)

167

Not support this operation

不支持此操作

168

ID2 has been suspended

ID2已暫停使用

169

ID2 has been discarded

ID2已廢棄

170

Permission denied, id2 has been blinded to other product key

ID2已綁定到其他產品,不容許在該產品使用;改回綁定的產品,或者刪除設備上的ID2,再重新空發一個新的ID2

171

Product key is invalid

ID2產品非法,如已廢棄

172

Product key is not exist

ID2產品不存在,產品錯誤填入,或者申請產品時,沒有選擇"ID2認證"

  1. ID2設備上線驗證:

  • 設備端ID2-iTLS建連成功后,在物聯網管理平臺,可看到新創建的設備和設備的上線信息。

  • 登錄物聯網平臺控制臺

  • 在左側導航欄,選擇設備管理 > 設備,DeviceName是ID2示例中設置的設備證書(ProductKey、DeviceName、DeviceSecret)設備名

  • 登錄IoT安全中心。

  • 在左側導航欄,選擇物聯網身份 > 設備身份認證,查看通過ID2激活的設備信息