SKF密码设备

GmSSL通过ENGINE机制支持密码硬件。鉴于《智能IC卡及智能密码钥匙密码应用接口规范》标准中公布了访问国密硬件的C语言API (下面简称SKF API),GmSSL通过ENGINE机制访问支持国密SKF API的国产密码硬件。

一个SKF API设备中可以包含一个或多个应用(Application),每个应用可以包含一个获多个容器(Container),每个容器中可以存放两对分别用于加密和签名的密钥对,以及两个相应的证书或证书链。每一个容器只能为ECC或RSA一种类型,一个容器中不能混用ECC密钥和RSA密钥。因此,在SKF API中提供公钥密码计算的接口通过Container Handle来引用公钥,容器的特性使得应用无需区分签名密钥和加密密钥,SKF API的实现会自动从容器中选择对应类型的密钥。

在使用公钥及访问容器时,应用需要进行两级认证,第一级为设备认证,第二级应用认证。设备认证需要全设备唯一的设备认证密钥,设备认证密钥是固定长度的对称密钥。访问某个具体的应用需要提供该应用的专有口令进行认证,认证的口令是可变长度的口令字符串。

GmSSL对设备认证规范做如下规定:

  1. 设备认证密钥固定为16字节
  2. 设备认证密码算法固定为SMS4 (SGD_SM4_ECB)。
  3. 设备发出的挑战数据是在调用SKF_DevAuth()之前,最后一次通过SKF_GenRandom()获取的16字节随机输出。
  4. 设备的响应数据为采用SMS4加密加密该16字节随机值后的密文

GmSSL对需要进行设备认证的场景做如下规定:

  1. SKF API的实现必须支持SKF_SetSymmKey()
  2. SKF_SetSymmKey()SKF_EncryptInit/Update/Final()等对称加密功能无需设备认证和应用认证
  3. 访问容器时需要进行两级认证

由于我们目前没有可以用于测试的在Linux/Mac上支持SKF API的硬件设备,因此GmSSL包含了一个SKF API的软件Dummy实现用于完成编译。GmSSL还提供了一个独立的测试程序,用于测试目标硬件是否满足GmSSL的规范和功能要求。

SKF Engine

GmSSL提供了一个通用的SKF Engine可以。

厂商提供硬件。

显示SKF引擎相关的信息

echo "[Commands]"
gmssl engine skf -vvvv
echo "[Capabilities]"
gmssl engine skf -c

初始化一个SKF设备

在使用SKF设备做签名、加密等密码操作的之前应该首先对设备进行初始化,主要的操作是在设备中生成或者导入SM2的私钥。

gmssl engine skf -pre VERBOSE:2 -pre SO_PATH:./libskf.so -pre SET_AUTHKEY:31323334353637383132333435363738

其中SO_PATH参数是厂商SKF动态库的地址,SET_AUTHKEY参数是设备认证密钥。SKF的设备认证密钥是16字节的对称密钥,SET_AUTHKEY参数要求设备认证密钥的32字符的HEX编码。

在设备打开的情况下,可以通过CHANGE_LABEL指令修改该SKF设备的标签,注意这个标签是一个字符串,长度不超过32个字符。

修改设备的认证密钥

gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre CHANGE_AUTHKEY:$AUTHKEY2

枚举系统中安装的SKF设备

gmssl engine skf -pre VERBOSE:2 -pre SO_PATH:$SO_PATH -pre LIST_DEVS

SKF接口在设计上支持一个设备中可以创建多个应用(Application),但是设备的厂商实现上可能只支持创建少数应用或者只支持创建仅一个应用,在这种情况下,如果设备中已经创建了应用,那么我们需先将已有的应用删除。

$SKF -pre OPEN_DEV:$DEVNAME -pre CREATE_APP:$APPNAME

枚举设备中的应用

gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre LIST_APPS

修改应用访问PIN

gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre CHANGE_PIN:USER
gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre CHANGE_PIN:ADMIN

创建应用

创建密钥容器


gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre CREATE_CONTAINER:sm2
gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre LIST_CONTAINERS

生成SM2私钥

$SKF $OPEN_APP -pre GEN_EC:sm2
gmssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:sm2p256v1 | $SKF $OPEN_APP -pre IMPORT_EC:sm2
gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre GEN_EC:sm2

导入私钥

gmssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:sm2p256v1 -pkeyopt ec_param_enc:named_curve | gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre IMPORT_EC:sm2

导入SM2证书

cat localhost-signcer.pem | gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre IMPORT_CERT:sm2.sign
cat localhost-kenccer.pem | gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre IMPORT_CERT:sm2.exch

导出证书

gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre EXPORT_CERT:sm2.sign
gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre EXPORT_CERT:sm2.exch

SM2签名与验签

echo "[Sign/Verify with SM2 Container]"
echo "abc" | gmssl sm3 -binary | gmssl pkeyutl -sign -pkeyopt ec_scheme:sm2 -engine skf -config skf.cnf -keyform engine -inkey sm2.sign -out sm2.sig
echo "abc" | gmssl sm3 -binary | gmssl pkeyutl -verify -pkeyopt ec_scheme:sm2 -engine skf -config skf.cnf -keyform engine -inkey sm2.sign -sigfile sm2.sig
echo "[Verify with exported SM2 Verification Public Key]"
gmssl pkey -engine skf -config skf.cnf -inform engine -in sm2.sign -pubout -out sm2vkey.pem
echo "abc" | gmssl sm3 -binary | gmssl pkeyutl -verify -pkeyopt ec_scheme:sm2 -pubin -inkey sm2vkey.pem -sigfile sm2.sig
echo "[Encrypt/Decrypt with SM2 Container]"
echo "Top Secret" | gmssl pkeyutl -encrypt -pkeyopt ec_scheme:sm2 -engine skf -config skf.cnf -keyform engine -inkey sm2.exch -out ciphertext.sm2
gmssl pkeyutl -decrypt -pkeyopt ec_scheme:sm2 -engine skf -config skf.cnf -keyform engine -inkey sm2.exch -in ciphertext.sm2
echo "[Encrypt with export SM2 Public Key, Decrypt with SM2 Container]"
gmssl pkey -engine skf -config skf.cnf -inform engine -in sm2.exch -pubout -out sm2ekey.pem
# only software encrypt/decrypt require ec_encrypt_param pkeyopt
echo "Top Secret" | gmssl pkeyutl -encrypt -pkeyopt ec_scheme:sm2 -ec_encrypt_param:sm3 -pubin -inkey sm2ekey.pem -out ciphertext.sm2
gmssl pkeyutl -decrypt -pkeyopt ec_scheme:sm2 -engine skf -config skf.cnf -keyform engine -inkey sm2.exch -in ciphertext.sm2

RSA容器

gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre CREATE_CONTAINER:rsa2048

生成RSA密钥

gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre GEN_RSA:rsa2048

导入RSA私钥

gmssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 | gmssl engine skf -pre VERBOSE:$VERBOSE -pre SO_PATH:$SO_PATH -pre SET_AUTHKEY:$AUTHKEY -pre OPEN_DEV:$DEVNAME -pre OPEN_APP:$APPNAME -pre IMPORT_RSA:rsa2048

GmSSL命令行的engine指令

SKF的配置文件

当使用engine之外的命令行指令时,如pkey等,这些是不支持engine-pre指令的,因此我们无法输入上述SKF命令。在这种情况下我们可以通过指定配置文件来输入参数

# conf file for gmssl skf engine
openssl_conf = openssl_init

[openssl_init]
engines = engine_section

[engine_section]
skf = skf_section

[skf_section]
engine_id = skf
VERBOSE = 1
SO_PATH = ./libSKF_final.so
SET_AUTHKEY = 31323334353637383132333435363738
OPEN_DEV = /media/guanzhi/Factory
OPEN_APP = MyApp1
init = 1

调用SKF引擎计算SM3

echo -n "abc" | sudo gmssl sm3 -engine skf -config skf.cnf -engine_impl

调用SKF引擎做SMS4加解密

echo -n "Message to be encrypted" | sudo gmssl sms4 -K 12345678123456781234567812345678 -iv 12345678123456781234567812345678 -a -engine skf -config skf.cnf

SM2加密

用SKF引擎实现加密和解密

echo "Top Secret" | gmssl pkeyutl -encrypt -pkeyopt ec_scheme:sm2 -engine skf -config skf.cnf -keyform engine -inkey sm2.exch -out ciphertext.sm2
gmssl pkeyutl -decrypt -pkeyopt ec_scheme:sm2 -engine skf -config skf.cnf -keyform engine -inkey sm2.exch -in ciphertext.sm2

从SKF引擎中导出公钥加密,用SKF引擎解密

gmssl pkey -engine skf -config skf.cnf -inform engine -in sm2.exch -pubout -out sm2ekey.pem
echo "Top Secret" | gmssl pkeyutl -encrypt -pkeyopt ec_scheme:sm2 -pkeyopt ec_encrypt_param:sm3 -pubin -inkey sm2ekey.pem -out ciphertext.sm2
gmssl pkeyutl -decrypt -pkeyopt ec_scheme:sm2 -engine skf -config skf.cnf -keyform engine -inkey sm2.exch -in ciphertext.sm2