国密算法实践经历(一)

作者: Timego | 来源:发表于2017-11-05 21:50 被阅读1022次

      不久前接到了单位的任务,内容是采用国密算法实现数据的加密操作。作为一个之前在加密算法经验基本为零的小白,从刚开始接到需求一脸迷茫到后来逐渐理出一些头绪。一路做下来有一些心得和体会,特写下此文记录一下这次新的尝试。文章计划从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
    

    相关文章

      网友评论

      • 菊部地区有黑洞iPhone:最新版本 2.3.2 不管是 armv7和arm64都编译有错误,不知道有没有最近有没有做这个的
      • 629ac46b37cb:现在armv7和arm64都编译成功了,但是模拟器版本的lib需要怎么配置呢?我看configure的配置里面没有对应的模拟器的target啊?求大神告知
        9b6aae154c3a:@lee65535 谢谢,我把632行那个int bits改为const unsigned int bits就可以编译下去了,然后又报错。。。
        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))
        629ac46b37cb:你注意看错误,是定义的类型和使用传递的参数不一致,需要修改一下,我也是github最新的代码,然后修改了一通才编译过的
        9b6aae154c3a:请问你是用github上最新的代码吗?
        我用最新的代码编译,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
      • 9b6aae154c3a:感觉分享,建议备注GmSSL版本,我用1.3.0才成功了,其他都不行。。。
        Timego:@哗然 抱歉 当时并没有想到备注编译版本
      • bd3cd373eda7:好厉害呀哈哈哈哈

      本文标题:国密算法实践经历(一)

      本文链接:https://www.haomeiwen.com/subject/ubrhmxtx.html