不久前接到了单位的任务,内容是采用国密算法实现数据的加密操作。作为一个之前在加密算法经验基本为零的小白,从刚开始接到需求一脸迷茫到后来逐渐理出一些头绪。一路做下来有一些心得和体会,特写下此文记录一下这次新的尝试。文章计划从GmSSL库的编译、SM2签名/验签/加密、SM3-HMAC、SM4的CBC/ECB加密等方面进行算法基础与代码实现的记录。由于经验尚浅,有不对的地方还望各位看官不吝赐教。
对于一个从来没有做过的东西,第一反应当然是在网络上进行搜索啦。经过一番搜索(以及付出了上百的CSDN积分T.T),最终决定通过GmSSL加密库来实现。
关于GmSSL
GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9等国密(国家商用密码)算法、SM2国密数字证书及基于SM2证书的SSL/TLS安全通信协议,支持国密硬件密码设备,提供符合国密规范的编程接口与命令行工具,可以用于构建PKI/CA、安全通信、数据加密等符合国密标准的安全应用。GmSSL项目是OpenSSL项目的分支,并与OpenSSL保持接口兼容。因此GmSSL可以替代应用中的OpenSSL组件,并使应用自动具备基于国密的安全能力。GmSSL项目采用对商业应用友好的类BSD开源许可证,开源且可以用于闭源的商业应用。GmSSL项目由北京大学关志副研究员的密码学研究组开发维护,项目源码托管于GitHub。自2014年发布以来,GmSSL已经在多个项目和产品中获得部署与应用,并获得2015年度“一铭杯”中国Linux软件大赛二等奖(年度最高奖项)与开源中国密码类推荐项目。GmSSL项目的核心目标是通过开源的密码技术推动国内网络空间安全建设。
按照官网的使用指南,在源代码下载完成后先将其解压至工作目录(笔者是直接下载到桌面)
注:编译环境:Xcode9.1/GmSSL版本:GmSSL 2.0 - OpenSSL 1.1.0d 26 Jan 2017
$ cd desktop
$ unzip GmSSL-master.zip
$ cd GmSSL-master
进行编译配置
$ ./Configure ios-cross
在这里笔者是需要编译出用于iOS平台使用的工程文件,所以选择了这样的配置。而且由于需要支持armv7/arm64/x86_64指令集,进行了多次的尝试后发现如需编译armv7的静态库,需要配置为iphoneos-cross。如果需要获得其他支持的编译配置,可以这样查看:
$ ./Configure --help
配置完成后,可以在工程目录下找到一个名为Makefile的文件,打开后进行修改(可直接搜索"cc= "找到需要修改的位置)。修改的地方有两处:
- CC 直接对等号后的内容进行替换。这里的路径是笔者Mac上的Xcode路径,编译的平台是arm64
CC=/Applications/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch arm64
- CFLAGS(就在CC的下一行) 只对-isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common 这段内容进行修改。修改的路径同样为笔者Mac上的Xcode路径,使用的SDK是写文章时最新的Xcode9.1 release版本iPhoneOS11.1.sdk,这个可以根据个人的编译器及SDK版本进行修改
CFLAGS=-DDSO_DLFCN -DHAVE_DLFCN_H -DNDEBUG -DOPENSSL_THREADS -DOPENSSL_NO_STATIC_ENGINE -DOPENSSL_PIC -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DVPAES_ASM -DECP_NISTZ256_ASM -DPOLY1305_ASM -DOPENSSLDIR=""$(OPENSSLDIR)"" -DENGINESDIR=""$(ENGINESDIR)"" -O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk
修改完成后保存并退出文件编辑,继续进行编译
$ make
在这里如果是使用和笔者一样的Xcode9.1 iPhoneOS11.1.sdk环境编译的话,应该也会遇到错误如下:
test/specktest.c:59:3: error: 'system' is unavailable: not available on iOS
system("pause");
^
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/stdlib.h:195:6: note:
'system' has been explicitly marked unavailable here
int system(const char *) __DARWIN_ALIAS_C(system);
^
test/specktest.c:65:3: error: 'system' is unavailable: not available on iOS
system("pause");
^
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/stdlib.h:195:6: note:
'system' has been explicitly marked unavailable here
int system(const char *) __DARWIN_ALIAS_C(system);
^
2 errors generated.
make[1]: *** [test/specktest.o] Error 1
make: *** [all] Error 2
这是因为在iOS 11中已经将'system'头文件及其方法禁用,按照报错信息将test/specktest.c中调用注释掉重新编译即可(测试代码不影响)。之后执行安装指令:
$ sudo make install
至此我们已经完成了GmSSL的编译,但由于iOS应用需要同时兼顾armv7/arm64/x86_64等指令集,所以还需要对源代码进行基于其他指令集的编译(ios-cross对应armv7、ios64-cross对应arm64、darwin-i386-cc对应i386,这里x86_64和i386的编译也可直接按照官方的Linux编译方式)。将对应指令集所需的libssl.a、libcrypto.a提取出来之后,直接删除刚刚编译好的工程文件夹(make clean指令清除不够彻底),即可进行再次编译。编译过程中可能会遇到如下报错:
/bin/sh: /usr/local/share/man/man3/hmac.3: Too many levels of symbolic links
make: *** [install_man_docs] Error 1
根据提示的路径/usr/local/share将share文件夹删除,重新编译即可。然后将编译出的静态库进行合成,用于iOS平台的GmSSL的编译就完成了
lipo -create libssl_armv7.a libssl_armv7s.a libssl_arm64.a libssl_x86.a -output libssl.a
lipo -info libssl.a
网友评论
crypto/saf/saf_keyhandle.c:89:7: error: implicit declaration of function
'RAND_bytes' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
|| !RAND_bytes(keybuf, EVP_CIPHER_key_length(cipher))
我用最新的代码编译,arm64都失败了
我的步骤如下步:
一./Configure ios64-cross
二修改该makefile
CC=/Applications/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch arm64
CFLAGS=-DDSO_DLFCN -DHAVE_DLFCN_H -DNDEBUG -DOPENSSL_THREADS -DOPENSSL_NO_STATIC_ENGINE -DOPENSSL_PIC -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DVPAES_ASM -DECP_NISTZ256_ASM -DPOLY1305_ASM -DOPENSSLDIR="\"$(OPENSSLDIR)\"" -DENGINESDIR="\"$(ENGINESDIR)\"" -O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.2.sdk
三make
然后就报错了
/Applications/Xcode.app/Contents/Developer/usr/bin/make depend && /Applications/Xcode.app/Contents/Developer/usr/bin/make _all
/Applications/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch arm64 -I. -Icrypto/include -Iinclude -DDSO_DLFCN -DHAVE_DLFCN_H -DNDEBUG -DOPENSSL_THREADS -DOPENSSL_NO_STATIC_ENGINE -DOPENSSL_PIC -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DVPAES_ASM -DECP_NISTZ256_ASM -DPOLY1305_ASM -DOPENSSLDIR="\"/usr/local/ssl\"" -DENGINESDIR="\"/usr/local/lib/engines-1.1\"" -O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.2.sdk -fPIC -MMD -MF crypto/aes/aes_core.d.tmp -MT crypto/aes/aes_core.o -c -o crypto/aes/aes_core.o crypto/aes/aes_core.c
crypto/aes/aes_core.c:632:5: error: conflicting types for 'AES_set_encrypt_key'
int AES_set_encrypt_key(const unsigned char *userKey, int bits,
^
include/openssl/aes.h:43:5: note: previous declaration is here
int AES_set_encrypt_key(const unsigned char *userKey, const unsigned int bits,
^
1 error generated.
make[1]: *** [crypto/aes/aes_core.o] Error 1
make: *** [all] Error 2