博客> iOS开发实现SM2加密(基于GmSSL的实现)
iOS开发实现SM2加密(基于GmSSL的实现)
2小时前 评论:0 阅读:3891 度灵使者
ios SM2加解密 GmSSL

近期由于公司项目的需要开始研究国密SM2加密.网上也找了许久没有,可是没有关于iOS方面的实现,有很多基于openssl的C语言的实现,但是因为是C的小白,而且代码较乱,也没注释,被坑了不少的下载积分.后来找到GmSSL有实现sm2.实现过程中遇到了各种的坑,同时也有其他小伙伴有这方面的需求,所以把我的实现过程分享一下.

一、下载GmSSL 先前去下载GmSSL,这个是官网地址:http://gmssl.org 另外github上也有也可以下载.( PS: 由于我是在5月份下载的,而最新的GmSSL中在sm2加密的方法中所传参数有所变动.不过影响不大,下面会讲到)

二、编译静态库 下面才是真正的有坑的地方.在GmSSL官网提供了一种编译方式,但是它编译出来的静态库是x86_64,对于iOS开发来说只支持模拟器的运行.经过研究我们需要用另一种编译方法. 1.在终端cd到GmSSL文件夹输入 ./Configure iphoneos-cross --prefix=/usr/local --openssldir=/usr/local/openssl 回车 2.找到GmSSL文件夹里面的makefilem文件,修改里面的两处地方 a、CC= 修改为 CC= /Applications/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch armv7s (PS:/Applications/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang 这个是你自己mac里面的路径,不过一般这个都是通用的.至于后面armv7s 自己根据需求给修改为 armv7 arm64 i386 获得的最后的静态库支持的就是现在填的) b、CFLAG= -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -O3 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fomit-frame-pointer -fno-common 修改后面一段为 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk (PS:这个路径同上,最后面的iPhoneOS的版本要根据你自己xcode的最高版本填,我写这篇文章时用的Xcode7.3,最高的就是9.3,这个自行修改) 3.回到终端 make 回车 4.sudo make install (如果报错信息为/usr/local/openssl/man/man3/hamc.3:*** 那么就找到/usr/local/openssl 这个文件夹,删除后重新sudo make install) GmSSL文件夹里面的两个.a文件,即是我们需要的静态库 5.合并静态库 -create /Users/a123456/Desktop/oldgmssl7/libssl.a /Users/a123456/Desktop/oldgmssl64/libssl.a /Users/a123456/Desktop/oldgmssl7s/libssl.a -output /Users/a123456/Desktop/oldgmssl/libssl.a

  • create 后面是原静态库的绝对路径 - output后面是合并后的静态库的绝对路径,这个需自己设置

    PS:在编译不同的只支持版本的静态库时,建议编译完成后删除文件夹,重新解压新的文件夹,make clean 命令不够彻底.

三、导入GmSSL到项目 只导入静态库是不行的,还需要.h文件.找到/usr/local/include/openssl 这个文件夹直接拉到项目中.另外在GmSSL中找到 crypto/sm2文件夹里面把除了sm2test.c的其他的.c文件全拉进项目里.

四、SM2加密 准备就绪就,开始动工,不多说,直接上代码

先加入头文件
sm2.h   和    ec_lcl.h

NSString * message = @"我爱北京天安门, 12 34 ~~~ 天安门上太阳升!!!!!!";
NSString * eckey = @"04F6E0C3345AE42B51E06BF50B98834988D54EBC7460FE135A48171BC0629EAE205EEDE253A530608178A98F1E19BB737302813BA39ED3FA3C51639D7A20C7391A";
const char * pubkey = [eckey UTF8String];
const char * message1 = [message UTF8String];

EC_KEY *ec_key = EC_KEY_new();
ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1);
const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key);
BN_CTX *ctx = BN_CTX_new();
EC_POINT * point1 = EC_POINT_hex2point(ec_group, pubkey, NULL, ctx);
ec_key -> pub_key = point1;

const char * encstr = test_sm2_enc(ec_key, message1);

NSString * encString = [NSString stringWithUTF8String:encstr];
NSLog(@"%@ %lu", encString, (unsigned long)encString.length);

//SM2加密
static const char * test_sm2_enc(EC_KEY * ec_key, const char * msg)
{
SM2_CIPHERTEXT_VALUE *cv = NULL;
cv = SM2_do_encrypt(EVP_sm3(), EVP_sm3(), (unsigned char *)msg, (size_t)strlen(msg), ec_key);
OPENSSL_assert(cv);

BN_CTX *ctx = BN_CTX_new();
char * hex = EC_POINT_point2hex(EC_KEY_get0_group(ec_key), cv -> ephem_point,              POINT_CONVERSION_UNCOMPRESSED, ctx);
//C1
NSMutableString * string = [NSMutableString stringWithUTF8String:hex];
//拼接C2
for (int i = 0; i < cv>ciphertext_size; i ++) {
    [string appendFormat:@"X", cv -> ciphertext[i]];
}
//拼接C3
for (int i = 0; i < cv>mactag_size ; i ++) {
    [string appendFormat:@"X", cv -> mactag[i]];
}

const char *char_content = [string cStringUsingEncoding:NSASCIIStringEncoding];
return char_content;
}

PS: 得到的结果是密文和密文长度.因为在加密过程中用到了随机数,所以每次加密结果不同.但是密文长度是固定的. 特别需要注意的是,由于GMSSL的更新,加密方法 cv = SM2_do_encrypt(EVP_sm3(), EVP_sm3(), (unsigned char *)msg, (size_t)strlen(msg), ec_key); 有所变动,由五个参数变为四个参数,大家需要注意修改.换汤不换药,是把那两个参数换成了结构体.解密没有代码实现,不过思路和流程和加密一毛一样,小伙伴们自行修改就行.如有什么疑问,或者意见,欢迎交流!

收藏
3
sina weixin mail 回到顶部