国密SKF库调用开发指南(一)

2023-11-16

在这里插入图片描述
针对支持国密算法USB KEY设备的应用,国家颁布一个行业标准《智能密码钥匙应用接口规范》(GM/T0016-2012),市面上销售的国密算法的USB KEY设备也都(其实也是必须)支持这个接口规范。因此,只要根据这个规范开发的应用程序,就可以兼容使用不同厂家及品牌的USB KEY产品。由于此规范中函数名称都以SKF开头,所以我们一般把按照此规范提供的设备开发接口库叫做SKF库或SKF接口。

一篇文章不可能介绍完SKF库里的所有接口,今天主要从开发的角度入手,按照实现几个主要功能的目的将涉及的接口和调用方式梳理一下,以帮助大家做相关开发。如果想看完整的接口说明,参考上面GM/T0016-2012标准即可。

在调用任何接口之前,都需要先加载所使用USBKEY设备的SKF库文件,这个文件是由KEY厂商提供,一般安装了USBKEY设备的相关软件就会有,具体文件名和存放路径要咨询厂商。加载方法与加载其他动态链接库无异:

::LoadLibrary(skfdllpath);

一、得到所有的国密证书(方法前的序号为调用顺序,下同)

根据国密标准,一种设备类型可以有多个设备(Device),每一个设备内可以有多个应用(Application),每一个应用里可以有多个容器(Container),每个容器里可以有一对证书(Certificate):签名证书和加密证书。因此,应按照下列顺序依次调用相关接口:

1.SKF_EnumDev(BOOL bPresent, LPSTR szNameList, ULONG *pulSize);

调用这个方法用来遍历当前电脑上的设备,这个方法的第一个参数一般传TRUE,表示遍历的是插上的设备;第二个参数就是返回的设备名称列表;第三个参数是设备名称列表缓冲区长度。按照惯例,这个方法应该被调用两次:第一次szNameList传NULL,pulSize返回长度;第二次给szNameList分配pulSize长度,返回设备列表,每个设备的名称以单个’\0’结束,以双’\0’表示列表的结束。

2.SKF_ConnectDev(LPSTR szName, DEVHANDLE *phDev);

通过循环调用这个方法用来连接每一个具体的设备,szName为设备名,即上面方法得到的列表中的设备名;返回phDev为设备句柄。

3.SKF_EnumApplication(DEVHANDLE hDev, LPSTR szAppNameList,ULONG *pulSize);

得到设备句柄后,再通过此方法枚举得到设备里的应用列表。hDev为连接设备时返回的设备句柄;szAppNameList返回应用名称列表;pulSize是列表缓冲区长度。这个方法也是照例要调用两次,不再赘述。同样,每个应用的名称以单个’\0’结束,以双’\0’表示列表的结束。

4.SKF_OpenApplication(DEVHANDLE hDev, LPSTR szAppName, HAPPLICATION *phApplication);

通过循环调用此方法打开应用列表里的每一个应用,hDev为连接设备时返回的设备句柄;szAppName是要打开的应用名称;phApplication为返回的应用句柄。

5.SKF_EnumContainer(IN HAPPLICATIONhApplication, OUT LPSTRszContainerNameList, OUT ULONG*pulSize)

拿到应用句柄后,我们就可以用此方法遍历应用中的所有容器了。hApplication是应用句柄;szContainerNameList是返回的容器名称列表;pulSize是列表长度;后面的就不用了多说了。

6.SKF_OpenContainer(HAPPLICATION hApplication,LPSTR szContainerName,HCONTAINER *phContainer);

循环调用此方法打开每一个容器。hApplication是应用句柄;szContainerName是要打开的容器名称;phContainer是返回的容器句柄。

7.SKF_ExportCertificate(HCONTAINER hContainer, BOOL bSignFlag, BYTE* pbCert, ULONG *pulCertLen);

最后就可以通过这个方法取得每个容器里的证书。hContainer是容器句柄;bSignFlag为导出的证书类型; TRUE表示导出的是签名证书;FALSE表示导出加密证书。pbCert为返回的证书数据,pulCertLen是证书数据的长度。同样需两次调用。

二、数字签名

在数字签名时,要指定签名所使用的证书。通过遍历本机上的证书,与签名用的证书进行对比,定位到签名证书在USBKEY中的位置,得到设备、应用和容器的句柄,然后使用证书的私钥进行签名。遍历对比的过程可参见上一节的内容。另外,由于数字签名会用到私钥,因此这里需要验证口令。

1.SKF_VerifyPIN(HAPPLICATION hApplication, ULONG ulPINType, LPSTR szPIN, ULONG *pulRetryCount);

此方法用来验证证书所在应用的PIN码,及上面说的口令,为后面的签名取得权限。hApplication是应用句柄;ulPINType是PIN类型,可以为0是管理员账户,1为普通用户,这个参数一般选择1。szPIN值是PIN码,pulRetryCount为出错后返回的重试次数。

2.SKF_ExportPublicKey(HCONTAINER hContainer, BOOL bSignFlag, BYTE* pbBlob, ULONG* pulBlobLen);

这个方法用来导出容器中的签名公钥,hContainer为证书所在容器句柄;bSignFlag 为导出密钥类型,TRUE表示导出签名公钥,FALSE表示导出加密公钥,这里选择TRUE;pbBlob为返回公钥的数据;pulBlobLen为数据的长度。这里这个方法可以不用调用两次,因为公钥结构是已知的,其长度也是固定的,因此可以直接为pbBlob分配固定长度的数据,以返回公钥。

3.SKF_DigestInit(DEVHANDLE hDev, ULONG ulAlgID, ECCPUBLICKEYBLOB *pPubKey, unsigned char *pucID, ULONG ulIDLen, HANDLE *phHash);

此方法进行杂凑(国密标准里把摘要称之为杂凑)运算初始化,并指定计算消息杂凑的算法。hDev为设备句柄;ulAlgID是杂凑算法标识,这里选择SGD_SM3(0x00000001),表明使用SM3算法;pPubKey为签名用证书公钥数据;pucID为签名者的ID值;ulIDLen是签名者的ID值的长度;phHash为返回的杂凑对象句柄。加入签名者ID值是SM2数字签名的一个重要特征,默认使用"1234567812345678"这个字符串值。

4.SKF_Digest(HANDLE hHash, BYTE *pbData, ULONG ulDataLen, BYTE *pbHashData, ULONG *pulHashLen);

初始化后,调用此方法进行数据杂凑运算。hHash是SKF_DigestInit方法返回的杂凑对象句柄; pbData为产生签名的原文,ulDataLen是原文数据的长度,pbHashData返回杂凑数据; pulHashLen返回杂凑结果的长度。同样,因为杂凑数据的长度都是固定的,这里同样可以为pbHashData事先分配固定长度,而不用再调用两遍。

注意,如果进行杂凑的数据是分组的,那就得使用下面两个方法:

SKF_DigestUpdate(HANDLE hHash, BYTE *pbData, ULONG ulDataLen);

SKF_DigestFinal(HANDLE hHash, BYTE *pHashData, ULONG *pulHashLen);

对每一组数据都使用SKF_DigestUpdate,最后调用SKF_DigestFinal返回杂凑值。当然,在数字签名运算中不存在分块计算签名的情况,所以这里也不会把数据分块杂凑。

5.SKF_ECCSignData(HCONTAINER hContainer, BYTE *pbData, ULONG ulDataLen, PECCSIGNATUREBLOB pSignature);

最后调用此方法进行数字签名。hContainer用来签名的私钥所在容器句柄,也就是遍历对比证书得到的容器句柄;pbData是被签名的数据;ulDataLen是被签名数据长度,必须小于密钥模长; pbSignature为返回的签名值。

三、验证签名

如果使用SKF库验证签名,可以按照下面的步骤:

1.SKF_CreateContainer(HAPPLICATION hApplication, LPSTR szContainerName, HCONTAINER *phContainer)

调用此方法创建一个临时容器。hApplication为容器所在的应用句柄;szContainerName是ASCII字符串,表示所建立容器的名称,最大长度不能超过64字节;phContainer是返回所建立容器的容器句柄。

2.SKF_ImportCertificate(HCONTAINER hContainer, BOOL bSignFlag, BYTE* pbCert, ULONG ulCertLen);

将签名用的证书导入到容器中。hContainer为容器句柄,即用上一方法创建的临时容器;bSignFlag为证书类型,TRUE表示签名证书,FALSE表示加密证书,这里选TRUE;pbCert,是证书数据;ulCertLen为证书数据长度;

3.SKF_ExportPublicKey(HCONTAINER hContainer, BOOL bSignFlag, BYTE* pbBlob, ULONG* pulBlobLen);

导出公钥。

4.SKF_DigestInit(DEVHANDLE hDev, ULONG ulAlgID, ECCPUBLICKEYBLOB *pPubKey, unsigned char *pucID, ULONG ulIDLen, HANDLE *phHash);

杂凑初始化。

5.SKF_Digest(HANDLE hHash, BYTE *pbData, ULONG ulDataLen, BYTE *pbHashData, ULONG *pulHashLen);

杂凑运算。

6.SKF_ECCVerify(DEVHANDLE hDev , ECCPUBLICKEYBLOB* pECCPubKeyBlob, BYTE *pbData, ULONG ulDataLen, PECCSIGNATUREBLOB pSignature);

进行签名验证。hDev是设备句柄;pECCPubKeyBlob是公钥数据结构,即第3步得到的公钥; pbData为待验证签名的数据;ulDataLen是待验证签名数据长度;pbSignature待验证的签名值。

7.SKF_DeleteContainer(HAPPLICATION hApplication, LPSTR szContainerName);

删除临时容器。hApplication为容器所在的应用句柄;szContainerName为容器名称。

可以看出,虽然基于某一种USBKEY设备SKF库可以实现验证签名,但这种方式要求系统安装SKF库并且很有可能在验证时也要插上设备(插不插设备具体要看SKF库的实现方式)。如果是数字签名操作这样要求无可厚非,但验证签名也这样就不切实际了。因为没有SKF库还可以安装,但验证签名时也要插入一个设备就说不过去了。因此,在实际应用中都是采用不依赖于设备的软实现验证方式。或者,等哪一个好心的第三方厂商开发一个基于软实现的SKF库。关于软实现的方式,已经超出了本文的范围。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

国密SKF库调用开发指南(一) 的相关文章

  • 树莓派 (Raspberry pi) 中文乱码

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 树莓派的操作系统是基于Debian 默认是没有中文的 如果需要显示中文 需要安装中文库 以下内容提供树莓派安装中文库的方法 1 安装命令 进入树莓派终端方式 可以通过 pu
  • Java的 多态性

    多态分为编译时多态和运行时多态 其中编辑时多态是静态的 主要是指方法的重载 它是根据参数列表的不同来 区分不同的函数 通过编辑之后会变成两个不同的函数 在运行时谈不上多态 而运行时多态是动态的 它是通过绑定 来实现的 也就是多态 多态的实现
  • 千锋网络安全1-3days

    千锋 网络安全笔记 总篇 持续更新 服务器 Windows00 03 08 12 Linux centos 虚拟机两种架构 寄生 一般在电脑主机 原生 直接安装在硬件上 虚拟机部署准备 安装Windows xp win7 Windows s
  • ROS学习(1)——ROS1和ROS2的区别

    因为机器人是一个系统工程 它包括了机械臂结构 电子电路 驱动程序 通信框架 组装集成 调试和各种感知决策算法等方面 任何一个人甚至是一个公司都不可能完成机器人系统的研发工作 但是我们又希望自己能造出一个机器人跑一跑 验证一下自己的算法 所以
  • Flutter 必备插件推荐

    前面两个不用说 flutter enhancement suite gt flutter代码增强提示 flutter snippets gt flutter模板快速生成代码 flutter image sync gt flutter 同步照
  • PyTorch训练LSTM时loss.backward()报错

    训练用PyTorch编写的LSTM或RNN时 在loss backward 上报错 RuntimeError Trying to backward through the graph a second time but the buffer
  • 从3dmax导出fbx格式模型的过程

    1 设置好单位 厘米 centimeters 3dmax默认导出的fbx文件导入到unity3d中的默认缩放因子是0 01 而unity3d默认单位为米 Customize unites setup metric centimeters s
  • C语言课程设计-单项选择题标准考试系统

    需求分析 1 设计题目 单项选择题标准考试系统 2 系统功能需求分析 能够答题 插入试题 查看题库试题 删除题库试题 最后退出系统五个功能 二 概要设计 2 1系统总体设计框架 功能模块说明 答题模块 2 3插入试题模块 确定插入题目数 选
  • QT报错解决方案

    QT报错 error multiple definition of mywidget mywidget QWidget 解决方案 Project created by QtCreator 2022 01 08T20 00 17 QT cor
  • Unity3d快速入门

    https www zhihu com question 313621072 Unity3d如何快速入门 前言 进入一个领域 最直接有效的方法就是 寻找相关综述性文章 首先你需要对你入门的领域有个概括性的了解 这些包括 1 主流的学习社区与
  • objectARX 定义块、删除定义块或快参照

    1 如何定义块 2 根据定义删除块 块参照 第一步 通过块定义名称找到实体idlist 当前图形数据库 gt 块表 gt 检查该块定义是否在块表存在 gt 存在 则通过定义名称 找到实体idlist 第二步 遍历块表的实体id 若属于某定义
  • ASP.NET Core3.1 跨平台智能云管理系统源码

    ASP NET Core3 1 跨平台智能云管理系统源码 一个相当不错的系统框架 ASP NET Core3 1 跨平台智能云管理系统 什么是 ASP NET Core ASP NET Core 是一个由微软创建的 用于构建 web 应用
  • 42. 疯狂爬取王者荣耀所有皮肤高清海报(文末源码)

    目录 前言 目的 思路 代码实现 1 导包 部署好环境 2 伪装请求头 3 访问英雄列表 获取英雄ID 4 分别访问各英雄主页 查看图片详情 5 写入本地文件夹 文件夹自动命名 完整源码 运行效果 总结 前言 阔别已久 各位粉丝朋友们 UP
  • MyBatis-Plus的主键策略

    MyBatis Plus的主键策略 我们在为主键挑选生成策略的时候 可以看出有一下几种策略 下面我们一起看看他们的生成方式 值 描述 AUTO 数据库ID自增 NONE 无状态 该类型为未设置主键类型 注解里等于跟随全局 全局里约等于 IN
  • 一图读懂JVM架构解析

    每个Java开发人员都知道字节码经由JRE Java运行时环境 执行 但他们或许不知道JRE其实是由Java虚拟机 JVM 实现 JVM分析字节码 解释并执行它 作为开发人员 了解JVM的架构是非常重要的 因为它使我们能够编写出更高效的代码
  • 实验三 虚拟局域网的配置

    一 实验目的和要求 1 理解以太网交换机IEEE802 1q扩展帧的转发 过滤 机制 2 理解虚拟局域网的功能和划分方法 3 理解STP协议工作机制 3 掌握单个交换机和跨交换机的VLAN配置 4 掌握三层交换机的配置 二 实验设备 1 双
  • 高防IP是什么?有什么作用?

    最近不少来咨询的客户都问什么是高防IP 客户接入这个高防IP的话需要做些什么准备 今天就给大家科普一下什么是高防IP 他的原理是什么 客户接入需要做些什么 高防IP是指高防机房所提供的IP段 主要是针对网络中的DDOS攻击进行保护 在网络世
  • CompiledEffect Direct3D9 Sample fxc.exe

    转载于 https www cnblogs com Agravity p 5138141 html
  • 微信小程序——自定义日期时间组件实现

    目前 微信小程序选择器提供了日期选择器 时间选择器等 但没有日期时间一体的选择器 当项目中需要进行日期时间选择时 我们只有自定义组件了 首先 我们需要先了解一下小程序的picker组件 详细使用见链接 https developers we
  • UDP通过广播的形式发送、接收结构体

    UDP是一种无连接的 面向数据包的传输协议 通过广播的方式可以向多个接收方发送数据 在C 中 可以使用socket库来实现UDP广播的发送和接收 下面是一篇CSDN博文 介绍了如何使用C 通过广播的形式发送和接收结构体 一 UDP广播的发送

随机推荐

  • 电商的1000+篇文章总结

    电商的1000 篇文章总结 本文收集和总结了有关电商的1000 篇文章 由于篇幅有限只能总结近期的内容 想了解更多内容可以访问 http www ai2news com 其分享了有关AI的论文 文章 图书 query 6 合并大舞台的背后
  • cocos2dx:瓦片地图加载失败及黑线问题

    问题 1 瓦片地图加载失败 运行时 获取瓦片地图的层失败 调试发现 获取的层是一个 NULL 遇到这个问题 我第一反应是图片路径有问题 但经过检查发现 路径没有问题 然我就怀疑 是我的代码有问题 然而并没有 调试无果 我就把目光转向瓦片地图
  • 23种设计模式之模板方法模式

    文章目录 模板方法模式 模板方法模式的优缺点 使用场景 模板方法模式 模板方法模式法 Template Method 定义一个操作中的算法骨架 而将算法的一些步骤延迟到子类中 使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤
  • pushd命令

    1 功能pushd命令常用于将目录加入到栈中 加入记录到目录栈顶部 并切换到该目录 若pushd命令不加任何参数 则会将位于记录栈最上面的2个目录对换位置2 语法 1 格式 pushd 目录 N N n 2 选项目录 将该目录加入到栈顶 并
  • 边界框回归的魔法:揭秘精准高效的MPDIoU损失函数

    文章目录 摘要 1 简介 2 相关工作 2 1 目标检测和实例分割 2 2 场景文本识别 2 3 边界框回归的损失函数 3 点距最小的并集交点 4 实验结果 4 1 实验设置 4 2 数据集 4 3 评估协议 4 4 目标检测的实验结果 4
  • 图神经网络与因果推理

    传统的因果推理基于线性结构方程模型 深度因果推理模型 这是基于图神经网络的模型 利用扁粉自动编码机来学习模型 其中 网络结构 因果推理模型为
  • iOS的终端命令和linux命令,iOS 终端 shell 操作,Mac 操作快捷键

    shell 操作命令 简单的shell 命令操作指令 pwd 当前工作目录 cd 不加参数 进root cd folder 进入文件夹 cd 上级目录 cd 返回root cd 返回上一个访问的目录 rm 文件名 删除 文件 rm 删除当前
  • vscode 配置文件

    将设置放入此文件中以覆盖默认设置 editor fontSize 18 editor fontFamily Source Code Pro Noto Sans CJK SC Consolas editor rulers 120 editor
  • 监听文件读取进度,中断文件读取

  • 使某个dom元素匀速滑动到容器顶部

    需求 我有个侧面的菜单 点击对应的菜单标题 可以让左侧的容易里对应标题滑到最顶上 于是我封装了一个缓动函数 这个函数接受3个参数 需要滚动的最外层的容器 滚动到什么距离 滚动时间 注意点 第一个参数的最外层的容器 需要滚动条 没滚动条是没有
  • Java AOP有5种增强方式注解——前置@Before,后置@After,返回@AfterReturning,异常@AfterThrowing,环绕@Around

    执行顺序 前置增强 gt 目标函数 gt 后置增强 gt 返回增强 异常增强 注意 Before After AfterRunning和 AfterThrowing修饰的方法没有返回值 而 Around修饰的方法必须有返回值 Aspect
  • 使用html制作3D循环相册

    使用 html 制作简单3D循环相册 注 img 标签中的 src 属性为你图片资源路径
  • typescript学习笔记

    typescript学习笔记 一 简介 typescript是js的超集 主要学习ts里面的原始类型 字面量类型 数组类型 函数类型 类类型 接口类型 类型别名 联合交叉类型 枚举类型 泛型等类型元素 以及类型推断 类型断言 类型缩小 类型
  • 开发BLE蓝牙手机上位机软件竟是如此的简单

    做安卓手机APP通常使用高端大气的Android Studio 开发语言是Java 该开发IDE就是体积大 学习成本高 入手慢 这里给大家推荐一款国产的软件 体积小 运行和编译速度快 最重要的是编程语言是中文 这个软件就是E4A 本次我将向
  • 【手把手】如何使用置信学习cleanlab对数据集进行去噪

    开源代码 https gitee com qq874455953 cleanlab nlp keras 目前可能是数据集选的不好 数据集本身没什么噪声 所以有点小问题 不过总体框架是搭建起来的 前言 在做一个项目的时候 发现数据集噪声非常多
  • Flink 多流转换 (五) 间隔联结(Interval Join)

    文章目录 间隔联结的调用 间隔联结实例 顾名思义 间隔联结的思路就是针对一条流的每个数据 开辟出其时间戳前后的一段时间间隔 看这期间是否有来自另一条流的数据匹配 间隔连接通过一个共同的key连接两个流 A B 中的数据 流 B 的数据具有时
  • 小红书sign算法-python实现

    coding utf 8 import hashlib def md5hex word if isinstance word unicode word word encode utf 8 elif not isinstance word s
  • git submodule拉取子模块最新代码

    转载请注明出处 https blog csdn net hhhhhhhhhhkkkkkkkkkk article details 122698629 之前由于对git子模块操作不熟悉 碰到子模块更新代码了本地死活拉取不到最新代码的问题 在网
  • 快速下载arxiv论文

    国内镜像站 http xxx itp ac cn 获得需要下载的论文id号 官网上会显示论文id 例如下载论文GAN的id为 1406 2661 那么 直接在浏览器上访问网址 http xxx itp ac cn pdf 1406 2661
  • 国密SKF库调用开发指南(一)

    针对支持国密算法USB KEY设备的应用 国家颁布一个行业标准 智能密码钥匙应用接口规范 GM T0016 2012 市面上销售的国密算法的USB KEY设备也都 其实也是必须 支持这个接口规范 因此 只要根据这个规范开发的应用程序 就可以