在IOS工程中使用OC调用C语言国密算法SM4(来替换DES算法)
来源:互联网 发布:淘宝客qq群拉人 编辑:程序博客网 时间:2024/06/17 02:38
我为什么写这篇博客呢,在网上可以搜到关于SM4的信息很多,代码基本都是c和java语言的,可是在ios里面和OC语言相互调用的网上还没有搜到。关于SM4算法的官方文档和源代码,见[中国互联网络信息中心官网](http://www.cnnic.net.cn/jscx/mixbz/sm4/)。提示:在上面网站的页面中点击“详见SM4算法”,可能有时打不开,可过几天再试。在实际调试时遇到很多问题,比如进制转换,有哪些输入的参数,输入的参数有什么格式要求,输出的是什么。在网上找到的源代码包含这四个文件: sm4.c sm4.h sm4test.c sms4.c先集成到ios工程中,直接运行报错:
duplicate symbol _main in: /Users/....../sm4test.o /Users/....../sms4.o
在sm4test.o和sms4.o中都定义了main函数,需要改名
- sm4test.c里面的main()改名为mainTest4()
- sms4.c里面的main()改名为mainSms4()
现在工程可以正常的运行起来了,为了调用上面这两个函数,为其添加两个对应的sm4test.h和sms4.h
//// sm4test.h// keyboardYU//// Created by yfc on 16/7/3.// Copyright © 2016年 yfc. All rights reserved.//#ifndef sm4test_h#define sm4test_hint mainTest4();#endif /* sm4test_h */
//// sms4.h// keyboardYU//// Created by yfc on 16/7/3.// Copyright © 2016年 yfc. All rights reserved.//#ifndef sms4_h#define sms4_hint mainSms4();#endif /* sms4_h */
在工程里需要的地方引入这两个头文件,这里以AppDelegate.m为例
在- (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions方法中调用:
//// AppDelegate.m// keyboardYU//// Created by yfc on 16/6/27.// Copyright © 2016年 yfc. All rights reserved.//#import "AppDelegate.h"#import "sm4test.h"#import "sms4.h"@interface AppDelegate ()@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { mainTest4(); mainSms4(); return YES;}@end
在控制台可以看到运行以上代码输出的是:
通过查看官方文档,可以确定:
- ECB模式下的明文和秘钥的值都是:01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
- 密文是:68 1e df 34 d2 06 96 5e 86 b3 e9 4f 53 6e 42 46
- 对一段明文反复加密100万次:59 52 98 c7 c6 fd 27 1f 04 02 f8 04 c3 3d 3f 66
当时做SM4的加解密时,遇到的问题现在分享给大家:
- SM4加密分为ECB和CBC模式,选用的是ECB
- SM4的明文必须是16的倍数,查了好多才查到,如果不是16的倍数要做数据填充Padding,不填充的话每次加密出来的数据都不一样,同样解密后也要去掉填充。(秘钥相同,明文相同,填充方式相同则密文一定相同)
- 加密时输入的是16位的秘钥和明文,输出密文
- 解密时输入的是16位的秘钥和密文,输出明文
- 明文和密文的长度是一样的(若不是16的倍数要算填充后的)
- 加解密调用的函数都是C的,接收和产生的数据类型都是char数组:unsigned char[],数组内容是16进制的。
- 在iOS中函数的返回值可以直接return
-(NSString *)add:(int)a andb:(int)b{
return [NSString stringWithFormat:@"%d",a+b];
}
在c语言中函数返回值不可以是char[],可以像这样写void sm4_crypt_ecb( sm4_context *ctx,
input是输入,output是输出,函数内部对output赋值,函数执行后,可以得到output的值。
int mode,
int length,
unsigned char *input,
unsigned char *output)
—–下面对源代码进行改造来和OC相互调用—–
// 1.将NSString类型的数据转成char[]类型 NSString *plainIn = @"this is plain text"; NSData *plainInData =[plainIn dataUsingEncoding:NSUTF8StringEncoding]; int dataLength =plainInData.length; ; unsigned char plainInChar[dataLength];// memcpy函数:将plainInData数据dataLength长度的部分复制到plainInChar里面 memcpy(plainInChar, plainInData.bytes, dataLength);// 说明:1.dataLength这个长度很重要,刚开始时候用过strlen和sizeof,,plainIn.length发现英文情况下没问题,中文的话数据会有缺失// 2.进制转换,要将平时的10进制数据转成16进制,在这里使用NSData它默认就是以16进制保存的,这里省略进制转换的步骤
// 2.对明文数据进行填充来保证位数是16的倍数,为了少声明一个变量在这里把填充和第1步放在一起 NSString *plainIn = @"this is plain text"; NSData *plainInData =[plainIn dataUsingEncoding:NSUTF8StringEncoding]; int plainInDataLength =plainInData.length; ;// p是需要填充的数据也是填充的位数 int p = 16 - plainInDataLength % 16; unsigned char plainInChar[plainInDataLength + p]; memcpy(plainInChar, plainInData.bytes, plainInDataLength);// 进行数据填充 for (int i = 0; i < p; i++) { plainInChar[plainInDataLength + i] = p; }
//3.验证一下填充后的char[]是不是最开始的明文数据 NSLog(@"plainInData=%@",plainInData); NSData *data = [[NSData alloc]initWithBytes:plainInChar length:sizeof(plainInChar)-p]; NSLog(@"data=%@",data); NSLog(@"填充后的char[]转成NSString=%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
可以看到数据是没有问题的
//4.对plainInChar加密,由于源代码中加解密是放在一起的,现在在sm4test.c中新添加两个方法把加密和解密分开,由于计算length总出问题,所以直接把length作为参数传进去void testEncodejiami(unsigned long lenght,unsigned char in[], unsigned char output[]){ unsigned char key[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; sm4_context ctx; //设置上下文和密钥 sm4_setkey_enc(&ctx,key); //加密 sm4_crypt_ecb(&ctx,1,lenght,in,output);}void testDecodejiemi(unsigned long lenght, unsigned char in[], unsigned char output[]){ unsigned char key[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; sm4_context ctx; //设置上下文和密钥 sm4_setkey_dec(&ctx,key); //解密 sm4_crypt_ecb(&ctx,0,lenght,in,output);}
//5.调用刚才添加的方法加密 //定义输出密文的变量 unsigned char cipherOutChar[plainInDataLength + p]; testEncodejiami(plainInDataLength + p, plainInChar, cipherOutChar); //对加密的数据输出 NSData *cipherTextData = [[NSData alloc]initWithBytes:cipherOutChar length:sizeof(cipherOutChar)]; NSLog(@"密文NSData=%@",cipherTextData); NSLog(@"密文转成NSString=%@",[[NSString alloc]initWithData:cipherTextData encoding:NSUTF8StringEncoding]);
输出结果是:
由于是加密数据,只有解密后才能转成NSString打印,所以第二行打印是null
//6将cipherTextData作为输入,调用第4步的解密方法,进行解密 //将data拷贝到字符数组中 unsigned char cipherTextChar[cipherTextData.length]; memcpy(cipherTextChar, cipherTextData.bytes, cipherTextData.length); //调用解密方法,输出是明文plainOutChar unsigned char plainOutChar[cipherTextData.length]; testDecodejiemi(cipherTextData.length, cipherTextChar, plainOutChar); //由于明文是填充过的,解密时候要去填充,去填充要在解密后才可以,在解密前是去不了的 int p2 = plainOutChar[sizeof(plainOutChar) - 1];//p2是填充的数据,也是填充的长度 int outLength = cipherTextData.length-p2;//明文的长度 //去掉填充得到明文 unsigned char plainOutWithoutPadding[outLength]; memcpy(plainOutWithoutPadding, plainOutChar, outLength); //明文转成NSData 再转成NSString打印 NSData *outData = [[NSData alloc]initWithBytes:plainOutWithoutPadding length:sizeof(plainOutWithoutPadding)]; NSString *str =[[NSString alloc]initWithData:outData encoding:NSUTF8StringEncoding]; NSLog(@"解密得到的明文是:%@",str);
到此解密成功,源代码已上传http://download.csdn.net/detail/qq_15509071/9607224
0 0
- 在IOS工程中使用OC调用C语言国密算法SM4(来替换DES算法)
- 在ios中调用C语言的国密算法SM2以替换RSA
- 如何在ios工程中用oc调用js算法
- 国密算法SM4,3DES算法和AES三种加密算法的java实现
- 【国密算法那点事儿】解读DES和SM4、RSA和SM2及SM3
- 【国密算法那点事儿】解读DES和SM4、RSA和SM2及SM3
- 【国密算法那点事儿】解读DES和SM4、RSA和SM2及SM3
- 国家密码算法SM4(国密算法)介绍
- 工程实践——DES算法的C语言实现
- 在JAVA中使用DES算法
- 在JAVA中使用DES算法
- 关于国密算法SM4的流程
- SM4国密算法实现分析
- SM4国密算法实现分析
- PHP实现国密算法SM4
- DES算法C语言源码
- C语言实现DES算法
- 【国密算法那点事儿】解读DES和SM4、RSA和SM2及SHA和SM3
- switch程序理解
- 正则表达式中的单个字符含义
- 五分钟战胜 Python 字符编码
- Launcher3桌面Icon的文字size的 修改
- Python入门:PIL之验证码破解
- 在IOS工程中使用OC调用C语言国密算法SM4(来替换DES算法)
- Linux 下串口编程入门
- MySQL索引原理及慢查询优化
- mybatis实战教程(mybatis in action),mybatis入门到精通
- 这10篇 iOS 热文,你别错过哦
- 1076. Forwards on Weibo
- android socket
- 自定义ProgressBar的进度色彩
- 使用Maven和Jersey Framework开发REST风格Web Service