通过阿里云物联网平台使用AI算法保护
1. 简介
- AI算法保护,提供内容的加密保护和全生命周期管理;授权过程的自动化和授权管理的统一化,防止内容的拷贝和泄漏,以及提供商业售卖的灵活性、安全性和管理成本。 
- 内容加密保护,一次性加密,多种许可分发和管理,支持不同的授权管理策略,满足不同场景的需求。 
- 基于IoT安全自建的设备认证产品(ID²),为内容保护提供全链路的安全保护。 
- 本文说明基于客户物联网平台提供的消息传输通道,使用AI算法保护,进行内容的加密保护和授权管理。 
2. 角色划分
接入AI算法保护会划分为两类角色,厂商需要根据不同的角色按步骤接入。
- 算法厂商:拥有AI算法的核心能力,在业务场景中会把算法授权到其它设备厂商使用。 
- 设备厂商:拥有自己的IoT设备,计划在IoT设备使用算法厂商所提供的算法。 
3. 对接流程
3.1 整体接入流程

3.2 算法厂商接入
3.2.1 服务开通(线下)
- 通过IoT安全中心官网AI算法保护模块,联系我们进行线下开通。 

3.2.2 模型加密(离线)
- 加密工具下载:服务开通后,通过点击AI算法保护-算法模型-离线加密工具,下载加密工具到本地,对原始的模型进行处理。 
- 模型加密工具:content_packager(Release Package/tools目录),运行在Ubuntu的可执行程序。 
- 模型加密工具 - 选项说明: 
| 参数 (均为string类型) | 说明 | 附注 | 
| --help | 打印该使用说明 | |
| --version | 打印内容打包工具的版本 | |
| --input | 待保护的文件 | 通过格式判定 | 
| --license | 支持2种情况: 
 | 
 | 
| --config | 保护配置文件(.json) | 用于配置模型文件的加密方式 | 
| --company | 公司名称 | 长度在4~8之间 | 
- 授权配置文件: 
- 打开license配置文件模板license_config.json,配置如下参数: 
| 参数 | 类型 | 说明 | 
| license_id | string | 
 | 
| extras | string | 用户数据,最长256 字节,超过会截断。 | 
| machine | string | 授权的设备id, 空则不绑定 | 
| valid_count | uint32 | 有效使用次数(-1 则无限制) | 
| valid_period_days | uint32 | 有效使用天数(-1 则无限制) | 
- 保护配置文件: 
- 打开保护配置文件模板protect_config.json,配置如下参数: 
| 参数 | 类型 | 说明 | 
| enc_type | string | 加密保护的内容类型: 
 | 
| enc_model | bool | true :打开分层加密 false:关闭分层加密(不改造算法模型) | 
| max_size | float | 最大加密的数据量(单位: MB): 
 | 
| sec_level | uint32 | 模型加密的安全强度(Security Level): 0 - 标准的AES加密 1 - 轻量的AES加密 | 
- 模型加密工具 - 使用示例: 
- 授权配置文件 - license_info.json,保护配置文件 - protect_config.json,模型文件 - googlenet.caffemodel: 
| ./content_packager --input googlenet.caffemodel --license license_info.json --config protect_config.json --company alibaba | 
- 输出如下: 
| <PACK_TOOL> version: 1.2.0 <PACK_TOOL> folder ./LD-0100-alibaba-2944-20210104095107 is created <PACK_TOOL> License: ./LD-0100-alibaba-2944-20210104095107/LD-0100-alibaba-2944-20210104095107.lic <PACK_TOOL> Encrypted Content: ./LD-0100-alibaba-2944-20210104095107/googlenet.caffemodel.enc <PACK_TOOL> Content Packager Finished | 
- 生成的加密文件为 <原始文件名称>.enc,License文件为 <license id>.lic 存放在以licence id命名的文件夹中。 
3.2.3 算法模型创建
如果算法厂商准备授权一种新的算法到设备厂商,首先需要对模型进行离线加密处理,然后完成算法模型创建。
- 点击新增算法模型按钮,会弹出新增算法模型窗口。 
- 输入算法厂商名称和算法模型名称。 
- 上传授权许可文件,该文件由离线加密工具输出<license_id>.lic。 
- 点击确认按钮完成算法模型新增。 

3.2.4 设备厂商授权
算法厂商首先完成算法模型创建,然后通过此步骤把算法授权到设备厂商。完成该步骤后,设备厂商拥有使用该算法的权限,设备厂商可以按照设备厂商角色相关步骤进行后续的接入操作。
- 请点击新增授权按钮,弹出新增授权窗口。 
- 输入授权名称、设备厂商阿里云账号UID,所关联的算法模型。(请确保输入有效的设备厂商阿里云账号UID) 
- 指定产品使用的授权配额,允许设备厂商特定数量的IoT设备使用所关联的算法模型。 
- 指定AI算法授权到期时间。(当AI算法到期后,IoT设备不能再使用所关联的算法模型) 
- 配置最大离线时间,(0~10000)小时,0表示允许永久离线。(当离线间隔到期后,IoT设备需要联网更新才能继续使用) 
- 点击确认按钮完成授权新增。 

3.2.5 查看使用记录
- 请点击AI算法保护-使用记录,可查看设备厂商的IoT设备连接云端平台获取授权的使用记录信息。 
- 数据总览界面。 
- 已购买授权:表示算法厂商购买的授权总额度。 
- 已分配:表示算法厂商已经分配到设备厂商的授权额度。 
- 已使用:表示算法厂商所授权的设备厂商已使用的授权数量。 
- AI算法模型:表示算法厂商所创建的算法模型数量。 
3.3 设备厂商接入
3.3.1 服务开通
- 请联系提供AI算法的算法厂商,并把自己阿里云账号UID提供到算法厂商,由算法厂商为其进行授权。 
- 当算法厂商授权完成后,设备厂商可以登录IoT安全中心 AI算法保护模块,查看算法授权信息。包括算法厂商名称,算法模型名称,LicenseID,授权有效期,以及授权额度等信息。 
3.3.2 创建产品
- 点击资产管理-直连设备-创建产品,弹出创建产品的窗口,选择我需要通过阿里云物联网平台,管理该产品下的设备。 

- 跳转到物联网平台控制台。 
- 点击选择的实例,在左侧导航栏,选择设备管理 > 产品,单击创建产品: 

- 选择设备管理->设备,单击添加设备: 
- 查看设备详细,获取设备证书(ProductKey、DeviceName、DeviceSecret)信息。 
3.3.3 关联产品
设备厂商首先完成产品创建,并记录产品的productKey信息,通过此步骤完成算法授权和产品的关联。完成该操作后,允许该产品下指定授权数量的IoT设备可以使用算法厂商所提供的算法。
- 选择需要进行关联的授权记录,点击关联产品。 
- 输入需要关联的产品ProductKey,如果还没完成产品创建请先完成产品创建。 
- 点击确认按钮完成产品关联。 

3.3.4 设备端对接
3.3.4.1 SAM SDK框架

- IoT Application: 
- 设备端需授权保护的应用模块,调用授权SDK接口进行许可鉴权,通过LP Linkkit进行授权许可消息上报和下发。 
- IoT Linkkit: 
- 阿里云物联网平台的接入SDK,提供IoT设备安全连接到阿里云IoT平台,提供数据连云的安全通道,以及业务数据的管理。 
- IoT安全SDK: 
- SAM:IoT授权许可模块。 
- ID²:IoT设备认证模块,SDK v3.1.0及以上。 
- OSA:操作系统适配接口,厂商需根据使用的OS,重新进行接口适配。 
- HAL:硬件适配接口,提供算法库和Soft-KM的适配接口,厂商需根据选择的硬件平台,重新进行接口适配。 
3.3.4.2 SAM SDK获取
- SAM SDK下载: 
- SAM Release Package目录: 
| 目录/文件 | 说明 | 
| app | 测试用例,包括HAL和SAM | 
| example | 演示和试用代码, 二级目录说明如下: deps: IoT Linkkit v2.3代码,只用作演示;项目如有需要,通过官网下载 HTTP - 提供基于HTTP协议的试用工程,包括demo app、License管理配置和消息转发 mqtt - 提供基于mqtt的端侧示例代码 | 
| include | 头文件 | 
| libs | 静态库 | 
| makefile | 编译脚本 | 
| make.rules | 编译系统配置文件,可配置编译工具链和编译参数 | 
| sample | 示例代码,本地环境的性能测试和试用 | 
| src | 需适配的OSA和HAL接口和参考实现 | 
| tools | 内容打包工具和配置模板 | 
- libs默认提供ID²-KM载体的静态库,其他载体如ID²-SE,可基于已适配和验证的ID²静态库进行替换,方法如下: 
- 获取ID²-SE的静态库:libid2.a, libicrypt.a和libkm.a 
- 打包生成最终的ID²静态库: 
    ar -x libid2.a
    ar -x libicrypt.a
    ar -x libkm.a
    ar rc libid2.a *.o
    ranlib libid2.a
    rm -rf *.o
    rm -rf libicrypt.a
    rm -rf libkm.a3.3.4.3 SAM SDK适配
- OSA接口适配: 
- 实现src/osa/ls_osa.c中的接口: 
- 已提供Linux系统的参考实现。 
- HAL接口适配: 
- ID²-KM载体: 
- KM HAL接口适配: 
- 实现deps/src/hal/km/demo/ls_hal_km.c中的接口: 
- 已提供Linux系统的参考实现: 

- 单独预留的KM安全分区大于2K, 且需保证在系统升级和重启时,分区数据不被破坏。 
- ls_hal_get_id接口,需使用设备硬件唯一标识。 
- SST HAL接口适配: 
- 实现deps/src/hal/sst/demo/ls_hal_sst.c中的接口: 
- 已提交Linux文件系统的参考实现: 

- 需要配置到真实的存储目录,且需保证在系统升级和重启时,分区数据不被破坏。 
- ID²-SE载体: 
- SST HAL接口适配: 
- 实现deps/src/hal/sst/demo/ls_hal_sst.c中的接口: 
- 已提供Linux文件系统的参考实现: 

- 需要配置到真实的存储目录,且需保证在系统升级和重启时,分区数据不被破坏。 
- SDK接口测试: 
- 修改makefile.rules的编译配置文件: 
- 配置目标平台(pLat := xxx)。 
- CROSS_COMPILE设置对应的编译工具链。 
- CFLAGS设置编译的配置参数。 
- 执行编译"make clean & make"。 
- HAL适配接口测试: 
- 正确运行程序hal_app,可得到如下成功日志: 
- " ============================> HAL SST Test Pass.“ 
........
- " ============================> HAL KM Test Pass.“ ->【只针对ID²-KM载体】 
- SAM接口单元测试: 
- 正确运行程序sam_test,可得到如下成功日志: 
- " =================>SAM Client Unit Test Pass.“ 
3.3.4.4 SAM SDK集成
- 授权初始化: 
主要完成授权SDK的初始化、上行安全通道和上行消息事件的注册,示例代码如下:
#include "sam_api.h"
#define SAM_SST_PATH     "./"                       // 安全存储路径
#define SAM_DEV_UUID     "1234-5678-8765-4321"      // 设备唯一硬件标识,如block id, chip id
static sam_context context = {0};
static int on_publish(const char *topic,
       const uint8_t *msg, uint32_t size, void *channel, const void *data)
{
     /*
      * TODO, Wrap and send SAM message through channel
      */
    
    return 0;
}
static void on_message(void *handle, void *channel, iotx_mqtt_event_msg_pt msg)
{
   if (!memcmp(SAM_SUB_TOPIC, ptopic_info->ptopic, ptopic_info->topic_len)) {
        sam_on_message(handle,
                       (uint8_t *)ptopic_info->payload,
                       (size_t)ptopic_info->payload_len);
    }
    return;
}
int License_Initiaze(char *product_name, char *device_name, void *channel)
{
    int ret = 0;
    sam_result result = SAM_SUCCESS;
    sam_config config;
    char pub_topic[128] = {0};
    char sub_topic[128] = {0};
 
    config.sst_path = SAM_SST_PATH;
    config.dev_uuid = SAM_DEV_UUID;
    config.timeout_ms = 10000;
    result = sam_set_config(&config);
    if (result != SAM_SUCCESS) {
        printf("sam set config fail, 0x%x\n", result);
        return -1;
    }
 
    result = sam_init_context(product_name, device_name, &context);
    if (result != SAM_SUCCESS) {
        printf("SAM init context fail, 0x%x\n", result);
        return -1;
    }
    result = sam_set_pub_handle(&context, on_publish, channel);
    if (result != SAM_SUCCESS) {
        printf("SAM set pub_handle fail, 0x%x\n", result);
        goto _out;
    }
    HAL_Snprintf(pub_topic, 128,
        SAM_PUB_TOPIC, product_name, device_name);
    HAL_Snprintf(sub_topic, 128,
        SAM_SUB_TOPIC, product_name, device_name);
    
    result = sam_set_pub_topic(&context, pub_topic);
    if (result != SAM_SUCCESS) {
        printf("SAM set pub topic fail, 0x%x\n", result);
        goto _out;
    }
    
    ret = IOT_MQTT_Subscribe(pclient,
              sub_topic, IOTX_MQTT_QOS1, on_message, &context);
    if (ret < 0) {
        printf("subscribe error");
        result = SAM_ERROR_GENERIC;
        goto _out;
    }
_out:
    if (result != SAM_SUCCESS) {
        sam_final_context(&context);
        return -1;
    } else {
        return 0;
    }
}
void License_Finalize(sam_context *context)
{
     sam_final_context(context);
}- product_name指产品标识(需是LP ProductKey),device_name设备唯一标识(可使用LP DeviceName,或其他设备硬件唯一标识),在同个产品product_name下唯一。 
- 在调用授权初始化时,需先完成安全通道的创建,其中channel为安全通道的句柄。 
- 授权初始化在应用/系统进程中,只需调用一次。 
- 注册的上行通道pub_handle,只需完成消息的上报。 
- 根据安全通道协议的特性,完成授权下行消息的识别和处理(如MQTT消息订阅)。 
- 可在sam_config中进行授权全局配置: 
- 设置请求超时时间(timeout_ms),超时时间有效值为1000ms - 20000ms, 当timeout_ms = 0时,使用默认的值10000ms。 
- 许可存储目录sst_path:SAM静态库集成时,使用HAL接口中设置,此处配置不生效。 
- 设备唯一标识dev_uuid:SAM静态库集成时,使用HAL接口中设置,此处配置不生效。 
- 授权内容解密: 
主要完成授权加密内容的解密,接口中会自动触发授权的申请、存储、加载和校验等动作,示例代码如下:
int license_content_decrypt(sam_context *context,
          char *license_name, uint8_t *in, uint32_t in_len, uint8_t *out, uint32_t *out_len)
{
    sam_result result;
    sam_session session;
    uint32_t lic_err = 0;
    result = sam_open_session(context, &session, license_name);
    if (result != SAM_SUCCESS) {
        printf("SAM open session fail, 0x%x\n", result);
        return -1;
    }
    
    result = sam_on_decryption(&session, in, in_len, out, out_len);
    if (result != SAM_SUCCESS) {
        printf("sam_on_decryption, 0x%x\n", result);
        if (result == SAM_ERROR_LICENSE_ERROR) {
            sam_get_lic_error_code(&session, &lic_err);
            printf("license error code, %d\n", lic_err);
        }
        goto _out;;
    }
    result = SAM_SUCCESS;
    
_out:
    sam_close_session(&session);
    
    if (result != SAM_SUCCESS) {
        return -1;
    } else {
        return 0;
    }
}- sam_on_decryption接口中包含sam_chk_lic_rights(授权许可的申请、存储和校验等)。 
- license_name,即时License ID,使用内容加密生成的许可文件名(不包含后缀),如不相同,程序会报错。 
- sam_on_decryption中调用sam_chk_lic_rights触发授权连云申请和校验,因此sam_on_decryption同样可能阻塞当前线程,因此sam_on_decryption和下行消息的处理需在不同线程中。 
- 注意事项: 
- SDK接口中product_name、device_name和license_name是字符串格式,有最大值限制(48、100、48)。 
- 配置的SDK的安全存储目录需预先创建,里面会保存授权相关的密钥和许可,此目录在正常使用、设备重启和系统升级时不会被擦除。 
- 单机授权在授权申请,以及发现异常(如撤销、过期、时间回滚等)会要求连网进行授权的云端校验,如此时网络不通/异常,接口sam_chk_lic_rights/sam_on_decryption会返回相应的错误,可在应用程序中显示对应的提示信息: 
- SAM_ERROR_REVOKED - 设备已经被撤销。 
- SAM_ERROR_LICENSE_ERROR - 设备授权错误,sam_get_lic_error_code获得错误码。 
- SAM_ERROR_TIMEOUT - 设备消息请求响应超时。 
- SAM_ERROR_CONMMUNICATION - 设备消息上报错误,需要连网。 
- 参考实现: 
- 离线环境 - 内容本地解密: 
- 示例代码:Release Package/sample/sam/sam_sample.c 
- 可基于此,进行内容解密的性能测试。 
- 联网环境 - 授权许可下发: 
- 示例代码:sample/sam/mqtt_sam_sample.c 
- 授权服务已经同LP打通,设备端可直接调用授权消息Topic进行授权许可消息的上报和下发。 
- 示例中的LP设备证书(ProductKey、DeviceName、DeviceSecret)和许可ID,需要替换成真实的数据。 
- LP Linkkit版本不同,Linkkit的接口可能不同,但授权消息Topic和调用接口保持不变。 
- LP Linkkit SDK获取: 
- Linkkit v4.x:获取C Link SDK 
- Linkkit其他发布版本:SDK获取 
3.3.5 调试验证
- 软件集成验证: 
- 模块集成SAM SDK后,在每次内容解密时,接口内部自动调用许可鉴权接口进行校验。 
- 在内容第一次解密时,由于设备上不存在许可缓存,因此需联网申请和下发许可。 
- 当设备上成功下发和存储授权许可,通过许可鉴权时,且内容解密成功,可通过日志查看许可信息: 

- License ID:许可唯一标识,SDK初始化时,由sam_open_session接口参数license_name传入。 
- License interval:许可的离线间隔,超过离线间隔,设备需再次联网更新许可。 
- License usage left_time:许可的有效剩余时间,单位为毫秒。 
- License usage count:许可的有效使用次数。 
- CRC32:保护内容的完整性校验因子,解密后,通过CRC32校验,说明内容解密正确。 
3.3.6 查看使用记录
- 请点击AI算法保护-使用记录,可查看IoT设备连接云端平台获取授权的使用记录信息。 
- 数据总览界面。 
- 已拥有授权:表示算法厂商为其授权的总配额信息。 
- 已使用:表示设备厂商已经使用的授权数量。