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 创建产品
点击资产管理-直连设备-创建产品按钮,弹出创建产品的窗口,选择我有自己的设备管理系统,只需要使用“物联网身份-设备身份认证”的能力。
输入产品名称,选择使用的密钥类型。
点击提交按钮完成产品创建。
3.2.3 关联产品
设备厂商首先完成产品创建,并记录产品的productKey信息,通过此步骤完成算法授权和产品的关联。完成该操作后,允许该产品下指定授权数量的IoT设备可以使用算法厂商所提供的算法。
选择需要进行关联的授权记录,点击关联产品。
输入需要关联的产品ProductKey,如果还没完成产品创建请先完成产品创建。
点击确认按钮完成产品关联。
3.2.4 服务端对接
3.2.4.1 授权消息格式:
通过物联网传输通道,在应用协议(如MQTT、HTTP)中增加特定的消息类型,标识上行和下行的授权消息。
上行授权消息,需包含的字段:
productKey:产品标识,字符串。
payload:设备授权请求数据,Base64格式。
下行授权消息,需包含的字段:
status:服务端POP接口的结果。
payload:设备授权响应数据,Bae64格式。
3.2.4.2 授权消息转发:
物联网平台,收到设备上报的授权消息请求时,调用授权POP接口,完成授权消息的转发处理,并将处理的结果和设备授权响应数据,通过传输通道下发到对应的设备端。
示例代码:
public static String samLicenseMessageProcess(String message) {
String productKey = null;
String payload = null;
DealDeviceRequestResponse response;
JSONObject inObj = JSON.parseObject(message);
if (inObj != null) {
productKey = inObj.getString("productKey");
payload = inObj.getString("payload");
}
DealDeviceRequestRequest request = new DealDeviceRequestRequest();
request.setProductKey(productKey);
request.setPayload(payload);
try {
response = client.getAcsResponse(request);
if (response.getSuccess() != true) {
System.out.println("deal device request, response = " + JSON.toJSONString(response));
return null;
}
} catch (ClientException e) {
e.printStackTrace();
System.out.println("deal device request, exception = " + e.getMessage());
return null;
}
JSONObject outObj = new JSONObject();
outObj.put("success", response.getSuccess());
outObj.put("data", response.getData());
return outObj.toJSONString();
}
上行的授权消息数据,定义成JSON格式,如下:
{
"productKey": "xxx",
"payload": "xxx"
}
下行的授权消息数据,可定义成JSON格式,如下:
{
"success": "true/false"
"data": "xxx"
}
3.2.5 设备端对接
3.2.5.1 SAM SDK框架:
IoT Application:
设备端需授权保护的应用模块,调用授权SDK接口进行许可鉴权,通过LP Linkkit进行授权许可消息上报和下发。
IoT传输通道:
客户物联网平台提供的数据连云的传输通道(上行和下行)。
IoT安全SDK:
SAM:IoT授权许可模块。
ID²:IoT设备认证模块,SDK v3.1.0及以上。
OSA:操作系统适配接口,厂商需根据使用的OS,重新进行接口适配。
HAL:硬件适配接口,提供算法库和Soft-KM的适配接口,厂商需根据选择的硬件平台,重新进行接口适配。
3.2.5.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.a
3.2.5.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.2.5.4 SAM SDK集成:
授权初始化:
主要完成授权SDK的初始化、上行安全通道和上行消息事件的注册,示例代码如下:
#include "sam_api.h"
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 *channel)
{
/*
* TODO, Parse and Call sam_on_message to process message
*/
return;
}
int do_license_initialize(char *product_name, char *device_name, void *channel, char *topic)
{
sam_result result;
sam_config config;
config.sst_path = NULL;
config.dev_uuid = NULL;
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;
}
result = sam_set_pub_topic(&context, topic);
if (result != SAM_SUCCESS) {
printf("SAM set pub topic fail, 0x%x\n", result);
goto _out;
}
_out:
if (result != SAM_SUCCESS) {
sam_final_context(&context);
return -1;
} else {
return 0;
}
}
void do_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
可基于此,进行内容解密的性能测试。
联网环境 - 授权许可下发:
示例代码:Release Package/example
提供基于Spring Boot的SP Server Demo,管理后台授权配置示例,以及授权消息的上下行交互逻辑。
3.2.6 调试验证
软件集成验证:
模块集成SAM SDK后,在每次内容解密时,接口内部自动调用许可鉴权接口进行校验。
在内容第一次解密时,由于设备上不存在许可缓存,因此需联网申请和下发许可。
当设备上成功下发和存储授权许可,通过许可鉴权时,且内容解密成功,可通过日志查看许可信息:
License ID:许可唯一标识,SDK初始化时,由sam_open_session接口参数license_name传入。
License interval:许可的离线间隔,超过离线间隔,设备需再次联网更新许可。
License usage left_time:许可的有效剩余时间,单位为毫秒。
License usage count:许可的有效使用次数。
CRC32:保护内容的完整性校验因子,解密后,通过CRC32校验,说明内容解密正确。
3.2.7 查看使用记录
请点击AI算法保护-使用记录,可查看IoT设备连接云端平台获取授权的使用记录信息。
数据总览界面。
已拥有授权:表示算法厂商为其授权的总配额信息。
已使用:表示设备厂商已经使用的授权数量。