概述

硬件锁即精锐5 硬件锁。在 Virbox LM 的产品和服务 一章中,我们简单描述了一下 Virbox 硬件锁许可的概念和特点,采用硬件锁来管理软件许可的方式之所以被大家青睐,其主要原因还是因为许可数据存储在硬件锁中是最为安全的,非常适合对软件安全强度、硬件性能及稳定性有极高要求的软件开发者。这是一款能真正对抗解密者的疯狂破译,经得起时间考验的优秀软件保护产品。

用户锁和开发锁

精锐5 加密锁有开发锁和用户锁之分,许多初次接触 Virbox LM 产品的开发者,很难弄清楚用户锁和开发锁的概念,这里简单介绍一下。用户锁和开发锁都是精锐5 加密锁,只是两者有不同的功能和用途。

精锐5 开发锁其实就是大家平时称呼的控制锁、母锁,是软件开发者拥有的加密锁,用来给用户锁签发许可和文件的加密锁,用户锁只能识别通过开发锁签发的许可和文件升级包,其他内容无法升级到用户锁内。开发锁对于开发者来说至关重要,须妥善保管。精锐5 用户锁是指随软件发布,最终发放给软件用户的加密锁,是开发者软件运行时的依赖,是许可的载体。有关用户锁和开发锁的详细描述请参考《精锐5 技术白皮书》精锐5分类

技术原理

首先,在加密锁的生产过程中,开发锁的开发商证书,已经下载到了每一把用户锁中,证书可以用来验证开发锁的数据签名,可以有效保证数据的来源。

其次,在开发锁签发许可或文件时,必须要得到用户锁的设备证书,这样可以保证使用设备公钥对数据进行加密,设备公钥加密可以保证每一个升级包都只能对应一个设备。

然后,精锐5 用户锁在升级许可或文件时,首先要使用用户锁的设备私钥对数据进行解密,然后使用开发商证书对数据进行验证,这样保证数据的唯一性和正确性,然后将许可数据或文件数据写入到用户锁中。

下图为加密锁许可的产生过程:

下图为加密锁许可的升级过程:

硬件锁许可条款

属性说明

许可版本

当前许可的版本号

许可ID

即产品ID,产品唯一标识码,取值 1--4,294,967,295

开始时间

软件不能早于这个时间,否则不可使用。支持范围:2000.1.1 00:00:00到2099.12.31 23:59:59

终止时间

软件不能晚于这个时间,否则不可使用。支持范围:2000.1.1 00:00:00到2099.12.31 23:59:59

第一次使用的时间

第一次登录许可的时间,用于实现时间跨度授权

时间跨度

以许可被访问后的第一次时间为基准,经过一定时长后许可失效

软件计次数

登录递减,当为0的时候许可失效

并发数,进程、网络等节点数目

为网络锁的并发节点数或者最大用户数,用来控制许可登录数量。

并发类型,进程并发、网络并发等为网络并发类型做限制

只读区

登录之后可以读取,但是不可写入。参考下文[许可用户数据区](#user_data)

读写区

登录之后可以读写,但是写入数据长度不能超过签发许可时设定的长度

公开区

数据只读不可写,用户可见

模块

只读不可写

升级流水号

许可签发的UTC时间秒

升级流水号

许可签发的UTC时间一秒之内的流水号

许可签发

使用开发者管理工具签发

简介

开发者工具是 Virbox LM 提供的本地可视化应用工具,用于帮助开发者快速签发硬件锁许可(开发者工具仅能用于签发硬件锁许可)。上面我们说到,签发许可和文件,必须要使用开发者特有的开发锁才能签发,因此使用 开发者工具 时也必须要用到开发锁。

适用场景

  • 本地化部署授权管理系统
  • 批量写锁操作
  • 签发离线升级包,用于远程升级

操作步骤

首先,打开开发者管理工具后,计算机插入开发锁,点击界面右上角的【开发锁PIN设置】,会弹出 PIN码 设置界面,我们在这里通过【执行PIN验证】输入开发锁的 PIN 码,有关开发锁 PIN 码的描述请查阅 开发锁 PIN码 使用手册

然后,在左侧【产品管理】一栏中,我们创建一个产品,通过创建产品来设置许可条款的基本信息。

再然后,左侧的【模板/授权】一栏中,我们创建一个模板,然后选择这个模板通过界面右上角的【发布许可】按钮,我们就可以发布一条硬件锁许可了,注意,这里我们还可以对许可的部分条款进行简单的修改。通过创建模板来设置许可的具体销售条款,之后进行许可签发。

最后,将精锐5 用户锁插入电脑,刷新本地锁,可以直接接将许可升级到用户锁中,如下图所示。

当然,如果精锐5 用户锁在用户手中,您可以根据用户锁的锁号,通过工具将许可写入一个本地文件(请记住这个文件,文件后缀为 .d2c,后面的操作我们会用到的)发送给用户,用户通过 Virbox 用户工具将升级文件升级到锁内,这是我们后面要讲的。

特别说明

将许可升级包存储为本地文件时,有一个问题,这里的精锐5 加密锁的信息从哪里来的?安装 SDK 的时候是不会附带的,您之前的所有签发都是有记录的,这些信息就是我们签发本地文件的依据。当然,我们也提供了精锐5 用户锁的生产数据包,您可以联系我们的 销售人员 获取生产数据,将生产数据导入到 开发者管理工具 的数据库中即可,有关精锐5 加密锁生产数据的管理,请参考  开发者管理工具用户手册 中的相关描述。

使用 Virbox 开发者中心 签发

简介

使用 Virbox 开发者中心签发硬件锁许可,是 Virbox LM 推出的一款增值服务。每一把精锐5 用户锁生产完成后,其相关的生产数据将上传至 Virbox LM 云平台,开发者可以通过 Virbox 开发者中心查看的购买到的加密锁信息,包括加密锁的基本信息,生产信息和用户锁的设备证书链,并根据这些信息针对指定的加密锁签发硬件锁许可。详情请登录 Virbox 开发者中心

适用场景

  • 不再设定具体写锁人员,希望降低管理成本;
  • 不再开发硬件锁升级工具/系统,降低研发维护成本;
  • 将空锁直接发给用户或对已有许可远程升级,减少交付时间;
  • 产品销售依赖于渠道或代理,对渠道的授权需要严格管理;

操作步骤

首先,我们在 Virbox 开发者中心 创建一款产品时,产品的许可形式要包含硬件锁,关于产品的许可形式我们前面提到过,这里不多做描述。

然后,创建相应的硬件锁许可模板。

最后,我们再签发许可。值得说明的是,这里硬件锁许可,是通过在线升级的,不需要用户手动升级文件,只需要用户锁插入电脑,许可会自动升级到加密锁中。当然,用户也可以通过 Virbox 用户工具 提供的在线升级功能手动触发升级效果,这一点,我们在后面的 硬件锁许可的升级 中有描述。您也可以参考 Virbox 用户工具许可在线升级,中描述的内容,这里更为详细。

使用 D2C API 签发

简介

Virbox SDK 提供了精锐5 加密锁许可管理的一整套开发库,方便您将加密锁管理流程集成到自己的管理系统中。其中就包括签发精锐5 用户锁许可,我们称为 D2C API。

适用场景

开发者可以集成授权管理功能到自己的管理系统中,对接企业 CRM、ERP 系统等。

操作步骤

您可以通过 Virbox SDK 开发者工具盒来找到开发库和相关示例代码,在开发包目录下,您可以查看到各种开发语言或操作系统的开发包,根据自己的需求选择开发包,开发您自己的加密锁签发工具。

使用 OpenAPI 签发

Virbox 云平台提供了完整的 后台 API,您可以通过调用 OpenAPI 来签发硬件锁许可,具体用法请参考《开发者中心开放接口V2.0》中的“硬件锁许可管理接口”。

许可升级

通过本地工具升级

在上文描述中,我们讲解了如何通过开发商管理工具来签发一条硬件锁许可,我们还提到了,若加密锁在您手中,则可以直接将许可升级到加密锁中。

若加密锁不在您手中,您可以生成一个本地文件发送给用户,通过 Virbox 用户工具 提供的数据包升级功能,将许可升级到加密锁中。如下图所示,许可直接发布到对应的加密锁中。

首先,我们打开 Virbox 用户工具,在左下角【高级】选项栏里找到【数据包升级】小工具。

然后,我们在小工具中,选择我们之前签发好的本地文件(文件后缀 .d2c 的文件),点击【升级】即可将许可升级到加密锁中。注意,这个过程中请保证用户锁在工具中被正常识别

在线升级

在上文的描述中,我们描述了如何通过 开发者中心来签发一条硬件锁许可,目标用户只需要将精锐5 硬件锁接入终端电脑,即可自动进行升级,当然,如果用户想主动进行升级,也可以在 Virbox 用户工具界面上操作,工具界面左侧选择【硬件锁】一栏,选择需要升级的硬件锁,右下角点击【在线升级】即可,如下图所示。具体介绍可以查看 Virbox 用户工具手册

自实现升级功能

在 Virbox 开发者工具盒 中,我们提供了一套完整的 SDK 开发包,可以实现加密锁许可的签发和升级操作,下面简单描述一下开发过程和注意事项,具体示例可参考 SDK 中相应的的 sample。

签发升级包

通过 D2C API 来实现升级包的签发,必要条件:开发锁。

D2C API 签发硬件锁许可

// 本示例演示如何签发一条许可,为方便起见,本示例仅设置一条许可ID,其他条款不做限制

SS_UINT32 add_license_d2c(D2C_HANDLE hD2c,SS_UINT32 licID)
{
	SS_UINT32 ret = 0;
    SS_CHAR lic_guid[D2C_GUID_LENGTH] = {0};

    cJSON *root = NULL;
    cJSON *data = NULL;

    root = cJSON_CreateObject();
    
    // 添加许可
    cJSON_AddStringToObject(root, "op", "addlic");
    // 强制写入(标识)
    cJSON_AddBoolToObject(root, "force", cJSON_True);
    // 许可ID = 1
    cJSON_AddNumberToObject(root, "license_id", licID);

	ret = d2c_add_lic(hD2c, cJSON_PrintUnformatted(root), "add license sample", lic_guid);
    if (root)
    {
        cJSON_Delete(root);
        root = NULL;
    }
	return ret;
}

int main(int argc, char **argv)
{
	SS_UINT32 i = 0;
	SS_UINT32 ret = 0;
	SS_CHAR strDevSn[SLM_LOCK_SN_LENGTH*2+1]	= {0};
	SS_BYTE deviceSn[SLM_LOCK_SN_LENGTH]		= {0};
	
	SS_BYTE p7b_cert[CERT_SIZE*3]				= {0};
	SS_UINT32 p7b_size							= CERT_SIZE*3;

	MASTER_HANDLE hmaster						= NULL;
	SS_CHAR* d2c								= NULL;
	SS_UINT32 d2c_len							= 0;
	D2C_HANDLE hD2c						= NULL;
    SS_CHAR d2c_filename[256]                   = {0};
	
	/************************************************************************/
	/*                 打开控制锁并创建D2C对象                              */
	/************************************************************************/
	ret = master_open(&hmaster);
	if (ret != 0)
	{
		printf("master_open error :0x%08X \n", ret);
		return -1;
    }

    // 新开发锁必须验证PIN码,否则无法使用
    ret = master_pin_verify(hmaster, "12345678", 8);
    if (ret != 0)
    {
        printf("masterPINVerify error :0x%08X \n", ret);
        return 1;
    }

	ret = d2c_lic_new(hmaster, &hD2c, ACCOUNT_TYPE_NONE, deviceSn, sizeof(deviceSn), p7b_cert, p7b_size);
	if (ret != 0)
	{
		printf("d2c_lic_new error :0x%08X \n", ret);
		master_close(hmaster);
		return 1;
	}
	/************************************************************************/
	/* 添加许可信息到d2c句柄并获取签发完成的许可  (支持添加多条许可信息)    */
	/************************************************************************/
	ret = add_license_d2c(hD2c, 1);
	if (ret != 0)
	{
		printf("add_license %d error :0x%08X \n", i+1, ret);
		master_close(hmaster);
		return 1;
	}

	//获取签发完的许可,获取buffer传入空,可获取到许可大小
	ret = d2c_get(hD2c, NULL, 0, &d2c_len);
	if (ret != 0 && d2c_len == 0)
	{
		printf("d2c_get error :0x%08X \n", ret);
	}
	else
	{
		d2c = (SS_CHAR*)malloc(d2c_len);
		ret = d2c_get(hD2c, d2c, d2c_len, &d2c_len);
		if (ret == SS_OK)
		{
            // 写入本地文件,升级至锁内需要通过 Runtime API  slm_update_ex() 接口,或者使用用户许可工具的加密锁数据升级工具。
            strcpy(d2c_filename, strDevSn);
			strcat(d2c_filename, ".d2c");
			write_file(d2c_filename, d2c, d2c_len);
			printf("生成D2C升级包成功:\n\t%s\n" ,d2c_filename);
		}
		else
		{
			printf("d2c_get buffer error :0x%08X\n", ret);
		}
		free(d2c);
	}
	master_close(hmaster);
	d2c_delete(hD2c);
	return ret;
}
CPP

升级许可

通过 Runtime API 来实现许可的升级,必要条件:用户锁。

许可升级

...
slm_update_ex(sn, d2c_buf, &err_msg);
...
CPP

小结

硬件锁在安全性和易用性上没有什么可挑剔的,但硬件锁毕竟是一个外设产品,在管理上会存在诸多的不便,尤其是加密锁已经发放到用户手中后,更难进行管理,有加密锁需要升级的,有加密锁丢失需要补锁的,所以这里我们其实是建议开发者使用 在线签发硬件锁许可 的,可以节省很大一部分的人力和管理成本。

另外,我们在 开发者管理工具用户手册 一文中,详细的介绍了设置不同形式的许可的操作方法,有需要的开发者可以移步浏览。