GmSSL初次探索 1.安装及命令行
GmSSL是一个支持国家加密算法标准GM/T的开源加密套件,由于它是OpenSSL的分支,因此保留了OpenSSL1.1.0的所有功能和API级别的兼容性。遗留项目如Apache的WEB Server可以通过很小的改动并重新编译就适配到GmSSL中。自2014年发布第一版以来,GmSSL被开源中国社区选为6个推荐的加密项目,同时也是2015中国linux软件奖得主。
GmSSL的安装步骤可以按照以下过程来:
#0. 安装环境 Ubuntu 18.04 LTS #1. 下载GmSSL源码 Github链接:https://github.com/guanzhi/GmSSL #2. 编译安装 在编译前可选择性地修改源码crypto/ec/ec_pmeth.c,第66行改为dctx->ec_encrypt_param = NID_sm3; 这里假设不做修改,以此配置、编译、安装 cd GmSSL/ ./config make sudo make install #3. 刷新动态链接库 默认配置下生成的libcrypto和libssl会安装在/usr/local/lib目录,并覆盖系统openssl中这两个库的软链接。 刷新库的话有可能造成部分系统应用无法使用,命令如下: sudo ldconfig 如果不刷,可以采用以下方法替代,将环境变量临时修改到安装包的目录,此时命令行可以照常使用: export LD_LIBRARY_PATH=$(pwd)
GmSSL的命令行操作和OpenSSL大同小异,这里演示用SM2标准生成公私钥对,并进行加解密运算。
#1. 生成密钥 // 这里输出了私钥为dkey.pem gmssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:sm2p256v1 -pkeyopt ec_param_enc:named_curve -out dkey.pem // 这里用私钥产生公钥ekey.pem gmssl pkey -pubout -in dkey.pem -out ekey.pem #2. 用公钥加密,私钥解密 // 加密”Top Secret”这句话并输出到cipher.sm2文件中 // 最后的选项在未改源码情况下必须要加的 echo “Top Secret” | gmssl pkeyutl -encrypt -pkeyopt ec_scheme:sm2 -pubin -inkey ekey.pem -out cipher.sm2 -pkeyopt ec_encrypt_param:sm3 // 同理,在添加该选项的情况下解密,结果会在终端输出 gmssl pkeyutl -decrypt -pkeyopt ec_scheme:sm2 -inkey dkey.pem -in cipher.sm2 -pkeyopt ec_encrypt_param:sm3 2.用GmSSL编程
这里实验了部分API的功能,由于时间有限而网络资料偏少,只测试通过了以SM2标准生成公私钥文件的功能。公钥加密功能出现运行错误,未来得及排查修改。测试代码如下,只保留了有用部分:
#include <openssl/conf.h> #include <openssl/evp.h> #include <openssl/err.h> #include <openssl/obj_mac.h> #include <openssl/ec.h> #include <openssl/pem.h> #include <stdio.h> int main(int arc, char *argv[]) { /* Load the human readable error strings for libcrypto */ ERR_load_crypto_strings(); /* Load all digest and cipher algorithms */ OpenSSL_add_all_algorithms(); /* Load config file, and other important initialisation */ OPENSSL_config(NULL); /* … Do some crypto stuff here … */ /* EVP函数 返回1表示成功;返回0表示错误;-1表示内部过程出错 */ /* 创建用于生成参数的上下文 */ EVP_PKEY_CTX *pctx = NULL; if(!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) goto err; if(EVP_PKEY_paramgen_init(pctx)!=1) goto err; /* 设置使用的椭圆曲线类型编号及加密算法 */ if(!EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2p256v1)) goto err; if(!EVP_PKEY_CTX_set_ec_param_enc(pctx, OPENSSL_EC_NAMED_CURVE)) goto err; /* 生成上下文密钥 */ EVP_PKEY *key = NULL; if(!EVP_PKEY_keygen_init(pctx)) goto err; if(!EVP_PKEY_keygen(pctx, &key)) goto err; /* 生成PEM格式文件密钥 */ FILE *fp1 = fopen(“1Priv.pem”,”w”); FILE *fp2 = fopen(“2Pubk.pem”,”w”); /* 输出私钥文件 */ if(!PEM_write_ECPrivateKey(fp1, EVP_PKEY_get1_EC_KEY(key), NULL, NULL, 0, NULL, NULL)) goto err; /* 输出公钥文件 */ if(!PEM_write_EC_PUBKEY(fp2, EVP_PKEY_get1_EC_KEY(key))) goto err; fclose(fp1); fclose(fp2); printf(“ALL procedures succeed!\n”); /* 在这里处理异常,方式为输出错误信息 */ err: { printf(“Exception occured!\n”); ERR_print_errors_fp(stderr); //将错误string输出标准错误 } /* Clean up */ /* Removes all digests and ciphers */ EVP_cleanup(); /* if you omit the next, a small leak may be left when you make use of the BIO (low level API) for e.g. base64 transformations */ CRYPTO_cleanup_all_ex_data(); /* Remove error strings */ ERR_free_strings(); return 0; }
编译并执行gcc -o 1elf main.c -lcrypto && ./1elf,会生成两个PEM格式密钥文件,可以用命令行代入它们加解密运算发现文件可用。
这里需要说的是代码中主要调用EVP部分的API。EVP(Envelop)函数是库中提供的高级API,其大部分API都和命令行参数有一一对应关系。有时要编写更细粒度的操作代码,则可以用一些低级API,如BIO函数及各个密码算法的对应API。
3.参考文献
当然,最重要的还是留下参考文献的链接,我认为有用的参考文档如下:
官网EVP库介绍(主要是对称加密函数和模板)http://gmssl.org/docs/evp-api.html
Openssl1.1.0官方Manual的crypto部分https://www.openssl.org/docs/man1.1.0/crypto/
项目Github仓库的Demos部分(公钥加密部分不多)https://github.com/guanzhi/GmSSL/tree/master/demos