如何在iOS中使用SM2进行数字签名及校验
来源:互联网 发布:单代号搭接网络计划sts 编辑:程序博客网 时间:2024/05/22 12:52
有网友留言关于sm2的数字签名,因此用了一天时间写完了,时间仓促,代码还有优化空间。
国家密码管理局发布SM2椭圆曲线公钥密码算法地址是:http://www.oscca.gov.cn/News/201012/News_1198.htm。文末的代码包里也会提供这个文档。
看过我的另一篇博客sm2公钥加密后,应该会比较了解了,这里就简单说一下签名。地址 http://blog.csdn.net/qq_15509071/article/details/51862664
关于数字签名 ,大概看了一下,对于程序员来讲最重要的应该是:
1.签名时候的输入参数:用户A的id,明文,用户A的私钥,用户A的公钥
2.签名时候的输出参数:签名(r,s)
3.椭圆曲线参数要使用pdf推荐的,不要使用pdf例子中的,因为实际使用都是按照推荐参数来的
4.验证签名输入的参数:用户A的id,用户A的公钥,收到的明文,收到的签名(r',s')
5.验证签名输出的参数:通过和不通过
6.这里随机数应该是自动生成的,现在写死,随机生成方法可以看sm2公钥的博客
7.导入openssl可以看sm2公钥的博客
下面直接粘代码,遇到什么问题,写的有不对的地方,欢迎指正
////数字签名//- (void)sedBtnClicked:(UIButton*)button { // //pdf文档的第一个例子// test_part2(sm2_param_fp_256, TYPE_GFp, 256); // //pdf文档的第二个例子 // test_part2(sm2_param_f2m_257, TYPE_GF2m, 257); //实际使用中// test_part2(sm2_param_recommand, TYPE_GFp, 256);// return; //用户A的id NSString *userId = @"ALICE123@YAHOO.COM"; NSData *userId_data = [userId dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"16进制的userId = %@",userId_data); //明文 NSString *data = @"message digest"; NSData *data_data = [data dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"16进制的data = %@",data_data); //私钥 NSString *pa = [@"128B2FA8 BD433C6C 068C8D80 3DFF7979 2A519A55 171B1B65 0C23661D 15897263" stringByReplacingOccurrencesOfString:@" " withString:@""]; NSData *pa_data = [self dataFromHexString:pa]; //公钥 NSString *px_ = [@"D5548C78 25CBB561 50A3506C D57464AF 8A1AE051 9DFAF3C5 8221DC81 0CAF28DD " stringByReplacingOccurrencesOfString:@" " withString:@""]; NSString *py_ = [@"92107376 8FE3D59C E54E79A4 9445CF73 FED23086 53702726 4D168946 D479533E" stringByReplacingOccurrencesOfString:@" " withString:@""]; NSData *px_data = [self dataFromHexString:px_]; NSData *py_data = [self dataFromHexString:py_]; //签名 char singResultR[1024]; char singResultS[1024]; sm2Sign([userId UTF8String],[data UTF8String],pa_data.bytes,px_data.bytes,py_data.bytes,singResultR,singResultS); //签名结果打印 NSData *Rdata = [[NSData alloc]initWithBytes:singResultR length: 64 ]; NSLog(@"密文data=%@", Rdata ); NSLog(@"密文r str=%@",[[NSString alloc]initWithData:Rdata encoding:NSUTF8StringEncoding] ); NSData *Sdata = [[NSData alloc]initWithBytes:singResultS length: 64 ]; NSLog(@"密文data=%@", Sdata ); NSLog(@"密文s str=%@",[[NSString alloc]initWithData:Sdata encoding:NSUTF8StringEncoding] ); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:[NSString stringWithFormat:@"r=%@,s=%@",[[NSString alloc]initWithData:Rdata encoding:NSUTF8StringEncoding],[[NSString alloc]initWithData:Sdata encoding:NSUTF8StringEncoding]] delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil]; [alert show]; }
void sm2Sign(char userAid[],char mingwen[],unsigned char pa[],unsigned char px[],unsigned char py[],char *singResultR,char *singResultS){ ec_param *ecp; sm2_ec_key *key_A; sm2_sign_st sign; ecp = ec_param_new(); ec_param_init(ecp, sm2_param_recommand, TYPE_GFp, 256); key_A = sm2_ec_key_new(ecp); sm2_ec_key_init(key_A, sm2_param_digest_d_A[ecp->type], ecp); memset(&sign, 0, sizeof(sign)); //这是要签名的消息 sign.message = (BYTE *)mingwen; sign.message_byte_length = strlen(mingwen); //这个签名者的id sign.ID = (BYTE *)userAid; sign.ENTL = strlen(userAid); sm2_hex2bin((BYTE *)sm2_param_digest_k[ecp->type], sign.k, ecp->point_byte_length); //取出私钥 公钥 的值 //设置pa for( int i=0;i<32;i++){ sign.private_key[i]=pa[i]; } //设置px for( int i=0;i<32;i++){ sign.public_key.x[i]=px[i]; } //设置py for( int i=0;i<32;i++){ sign.public_key.y[i]=py[i]; }// sm2_bn2bin(key_A->d, sign.private_key, ecp->point_byte_length);// sm2_bn2bin(key_A->P->x, sign.public_key.x, ecp->point_byte_length);// sm2_bn2bin(key_A->P->y, sign.public_key.y, ecp->point_byte_length); DEFINE_SHOW_STRING(sign.public_key.x, ecp->point_byte_length); DEFINE_SHOW_STRING(sign.public_key.y, ecp->point_byte_length); //dd这里是签名 char singResultR_[1024]; char singResultS_[1024]; sm2_sign(ecp, &sign,singResultR_,singResultS_); printf("px\n"); for( int i=0;i<64;i++){ printf("%c", singResultR_[i]); } printf("\n"); memcpy(singResultR, singResultR_, 64); memcpy(singResultS, singResultS_, 64); sm2_ec_key_free(key_A); ec_param_free(ecp); }
//签名验证- (void)thirdBtnClicked:(UIButton*)button { //用户A的id NSString *userId = @"ALICE123@YAHOO.COM"; NSData *userId_data = [userId dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"16进制的userId = %@",userId_data); //明文 NSString *data = @"message digest"; NSData *data_data = [data dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"16进制的data = %@",data_data); //公钥 NSString *px_ = [@"D5548C78 25CBB561 50A3506C D57464AF 8A1AE051 9DFAF3C5 8221DC81 0CAF28DD " stringByReplacingOccurrencesOfString:@" " withString:@""]; NSString *py_ = [@"92107376 8FE3D59C E54E79A4 9445CF73 FED23086 53702726 4D168946 D479533E" stringByReplacingOccurrencesOfString:@" " withString:@""]; NSData *px_data = [self dataFromHexString:px_]; NSData *py_data = [self dataFromHexString:py_]; //r NSString *r = @"077BA4656350DAEEA3656EE042DDECE22D5E8DCA4882CB20080AD26E2CB62E9F"; NSData *rData = [self dataFromHexString:r]; //s NSString *s = @"2BF329F4AFF86EEE0F924888DDE20BF12A21B638A3B0F1FCA70395C4BE00D0AC"; NSData *sData = [self dataFromHexString:s]; int result = sm2CheckSign([userId UTF8String],[data UTF8String],px_data.bytes,py_data.bytes,rData.bytes,sData.bytes); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:[NSString stringWithFormat:@"%d",result] delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil]; [alert show]; }
//校验签名int sm2CheckSign(char userAid[],char mingwen[],unsigned char px[],unsigned char py[],char *singResultR,char *singResultS){ ec_param *ecp;// sm2_ec_key *key_A; sm2_sign_st sign; ecp = ec_param_new(); // ec_param_init (ecp,sm2_param_fp_256, TYPE_GFp, 256);//pdf例子 ec_param_init(ecp, sm2_param_recommand, TYPE_GFp, 256);//实际 // key_A = sm2_ec_key_new(ecp); // sm2_param_digest_d_A[ecp->type]貌似是私钥// sm2_ec_key_init(key_A, sm2_param_digest_d_A[ecp->type], ecp); memset(&sign, 0, sizeof(sign)); //设置r s for( int i=0;i<32;i++){ sign.r[i] = singResultR[i]; printf("%02x", sign.r[i]);} printf("\n"); for( int i=0;i<32;i++){ sign.s[i] = singResultS[i]; printf("%02x", sign.s[i]); } printf("\n"); //这是要签名的消息 sign.message = (BYTE *)mingwen; //验证时不用这个参数吗 // for( int i=0;i<32;i++){// sign.Z[i] = mingwen[i];// printf("%02x", sign.Z[i]);// // } sign.message_byte_length = strlen(mingwen); //这个签名者的id sign.ID = (BYTE *)userAid; sign.ENTL = strlen(userAid); //k 随机数 sm2_hex2bin((BYTE *)sm2_param_digest_k[ecp->type], sign.k, ecp->point_byte_length); //设置px for( int i=0;i<32;i++){ sign.public_key.x[i]=px[i]; } //设置py for( int i=0;i<32;i++){ sign.public_key.y[i]=py[i]; } memset(sign.private_key, 0, sizeof(sign.private_key)); //«Â≥˝ÀΩ‘ø char singResultR_[1024]; //验证签名 sm2_verify(ecp, &sign,singResultR_); for( int i=0;i<32;i++){ if (singResultR[i] == singResultR_[i]) { printf("%c", singResultR_[i]); }else{ return 0; } } // sm2_ec_key_free(key_A); ec_param_free(ecp); return 1;}
//这里面打印比较多,因为遇到一个问题void sm2_verify(ec_param *ecp, sm2_sign_st *sign,char *singResulR){sm2_hash e;BIGNUM *e_bn;BIGNUM *t;BIGNUM *R;xy_ecpoint *result;xy_ecpoint *result1;xy_ecpoint *result2;xy_ecpoint *P_A;BIGNUM *r;BIGNUM *s;BIGNUM *P_x;BIGNUM *P_y;e_bn = BN_new();t = BN_new();R = BN_new();result = xy_ecpoint_new(ecp);result1 = xy_ecpoint_new(ecp);result2 = xy_ecpoint_new(ecp);P_A = xy_ecpoint_new(ecp);r = BN_new();s = BN_new();P_x = BN_new();P_y = BN_new(); //bignum和byte转换 r s x yBN_bin2bn(sign->r, ecp->point_byte_length, r);BN_bin2bn(sign->s, ecp->point_byte_length, s);BN_bin2bn(sign->public_key.x, ecp->point_byte_length, P_x);BN_bin2bn(sign->public_key.y, ecp->point_byte_length, P_y);xy_ecpoint_init_xy(P_A, P_x, P_y, ecp); //wo复制过来 的 获取sign z 与 z_a sm2_hash Z_A; memset(&Z_A, 0, sizeof(Z_A)); Z_A.buffer[0] = ((sign->ENTL * 8) >> 8) & 0xFF; Z_A.buffer[1] = (sign->ENTL * 8) & 0xFF; Z_A.position = Z_A.position + 2; BUFFER_APPEND_STRING(Z_A.buffer, Z_A.position, sign->ENTL, sign->ID); BUFFER_APPEND_BIGNUM(Z_A.buffer, Z_A.position, ecp->point_byte_length, ecp->a); BUFFER_APPEND_BIGNUM(Z_A.buffer, Z_A.position, ecp->point_byte_length, ecp->b); BUFFER_APPEND_BIGNUM(Z_A.buffer, Z_A.position, ecp->point_byte_length, ecp->G->x); DEFINE_SHOW_STRING(Z_A.buffer, Z_A.position);// 0090414C 49434531 32334059 41484F4F 2E434F4D 787968B4 FA32C3FD 2417842E// 73BBFEFF 2F3C848B 6831D7E0 EC65228B 3937E498 63E4C6D3 B23B0C84 9CF84241// 484BFE48 F61D59A5 B16BA06E 6E12D1DA 27C5249A 421DEBD6 1B62EAB6 746434EB// C3CC315E 32220B3B ADD50BDC 4C4E6C14 7FEDD43D BUFFER_APPEND_BIGNUM(Z_A.buffer, Z_A.position, ecp->point_byte_length, ecp->G->y); DEFINE_SHOW_STRING(Z_A.buffer, Z_A.position);// 0090414C 49434531 32334059 41484F4F 2E434F4D 787968B4 FA32C3FD 2417842E// 73BBFEFF 2F3C848B 6831D7E0 EC65228B 3937E498 63E4C6D3 B23B0C84 9CF84241// 484BFE48 F61D59A5 B16BA06E 6E12D1DA 27C5249A 421DEBD6 1B62EAB6 746434EB// C3CC315E 32220B3B ADD50BDC 4C4E6C14 7FEDD43D 0680512B CBB42C07 D47349D2// 153B70C4 E5D7FDFC BFA36EA1 A85841B9 E46E09A2 BUFFER_APPEND_BIGNUM(Z_A.buffer, Z_A.position, ecp->point_byte_length, P_x); DEFINE_SHOW_STRING(Z_A.buffer, Z_A.position); //p_x0AE4C779 8AA0F119 471BEE11 825BE462 02BB79E2 A5844495 E97C04FF 4DF2548A BUFFER_APPEND_BIGNUM(Z_A.buffer, Z_A.position, ecp->point_byte_length, P_y); //py 7C0240F8 8F1CD4E1 6352A73C 17B7F16F 07353E53 A176D684 A9FE0C6B B798E857 DEFINE_SHOW_STRING(Z_A.buffer, Z_A.position);// 0090414C 49434531 32334059 41484F4F 2E434F4D 787968B4 FA32C3FD 2417842E// 73BBFEFF 2F3C848B 6831D7E0 EC65228B 3937E498 63E4C6D3 B23B0C84 9CF84241// 484BFE48 F61D59A5 B16BA06E 6E12D1DA 27C5249A 421DEBD6 1B62EAB6 746434EB// C3CC315E 32220B3B ADD50BDC 4C4E6C14 7FEDD43D 0680512B CBB42C07 D47349D2// 153B70C4 E5D7FDFC BFA36EA1 A85841B9 E46E09A2 //后面不一样0AE4C779 8AA0F119 471BEE11// 825BE462 02BB79E2 A5844495 E97C04FF 4DF2548A 7C0240F8 8F1CD4E1 6352A73C// 17B7F16F 07353E53 A176D684 A9FE0C6B B798E857 SM3_Init(); SM3_Update(Z_A.buffer, Z_A.position); SM3_Final_byte(Z_A.hash); memcpy(sign->Z, Z_A.hash, HASH_BYTE_LENGTH); DEFINE_SHOW_STRING(Z_A.hash, HASH_BYTE_LENGTH);//F4A38489 E32B45B6 F876E3AC 2168CA39 2362DC8F 23459C1D 1146FC3D BFB7BC9A // 不一样 //wo复制过来 的 //z是杂凑值 和msgmemset(&e, 0, sizeof(e));BUFFER_APPEND_STRING(e.buffer, e.position, HASH_BYTE_LENGTH, sign->Z);BUFFER_APPEND_STRING(e.buffer, e.position, sign->message_byte_length, (BYTE*)sign->message); DEFINE_SHOW_STRING(sign->Z, HASH_BYTE_LENGTH);//F4A38489 E32B45B6 F876E3AC 2168CA39 2362DC8F 23459C1D 1146FC3D BFB7BC9A DEFINE_SHOW_STRING(e.buffer, HASH_BYTE_LENGTH + 100);//F4A38489 E32B45B6 F876E3AC 2168CA39 2362DC8F 23459C1D 1146FC3D BFB7BC9A 6D657373 61676520 64696765 73740000 DEFINE_SHOW_STRING(e.hash, HASH_BYTE_LENGTH);//0 SM3_Init();SM3_Update(e.buffer, e.position);SM3_Final_byte(e.hash);BN_bin2bn(e.hash, HASH_BYTE_LENGTH, e_bn); DEFINE_SHOW_STRING(e.buffer, HASH_BYTE_LENGTH);//E6E831E4 6D338322 F431ED5A C3364483 E9372D4B 7795EF54 5D68E91C 583A6693 DEFINE_SHOW_STRING(e.hash, HASH_BYTE_LENGTH);//B524F552 CD82B8B0 28476E00 5C377FB1 9A87E6FC 682D48BB 5D42E3D9 B9EFFE76 //DEFINE_SHOW_BIGNUM(e_bn); DEFINE_SHOW_BIGNUM(e_bn);//B524F552 CD82B8B0 28476E00 5C377FB1 9A87E6FC 682D48BB 5D42E3D9 B9EFFE76 BN_mod_add(t, r, s, ecp->n, ecp->ctx); DEFINE_SHOW_BIGNUM(result1->x); DEFINE_SHOW_BIGNUM(result1->y); DEFINE_SHOW_BIGNUM(ecp->G->x);//32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7 DEFINE_SHOW_BIGNUM(ecp->G->y);//BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0 DEFINE_SHOW_BIGNUM(s);//2BF329F4 AFF86EEE 0F924888 DDE20BF1 2A21B638 A3B0F1FC A70395C4 BE00D0AC DEFINE_SHOW_BIGNUM(result2->x); DEFINE_SHOW_BIGNUM(result2->y); DEFINE_SHOW_BIGNUM(P_A->x);//D5548C78 25CBB561 50A3506C D57464AF 8A1AE051 9DFAF3C5 8221DC81 0CAF28DD DEFINE_SHOW_BIGNUM(P_A->y);//92107376 8FE3D59C E54E79A4 9445CF73 FED23086 53702726 4D168946 D479533E DEFINE_SHOW_BIGNUM(t);//336ECE5A 134949DC B2F7B769 20BFF8D3 57804402 EC33BD1C AF0E6832 EAB6FF4B DEFINE_SHOW_BIGNUM(result->x); DEFINE_SHOW_BIGNUM(result->y); xy_ecpoint_mul_bignum(result1, ecp->G, s, ecp); DEFINE_SHOW_BIGNUM(result1->x);//68D957D2 FA010371 C76F7B1C 9370D4B5 35E2A712 9FB7627A BF76F27B BC33A660 DEFINE_SHOW_BIGNUM(result1->y);//8BB516B0 ABBD3CCE 34415612 F439203A FDC1BFA2 CBF0EA63 D1C0D07C A2E32FCC DEFINE_SHOW_BIGNUM(result2->x); DEFINE_SHOW_BIGNUM(result2->y); DEFINE_SHOW_BIGNUM(result->x); DEFINE_SHOW_BIGNUM(result->y); xy_ecpoint_mul_bignum(result2, P_A, t, ecp); DEFINE_SHOW_BIGNUM(s); DEFINE_SHOW_BIGNUM(result2->x);//31F17670 3062F3C8 C375F85E 2F8AA60C 9D8FFA70 DFBB9EA4 E3F9C3E7 7E72D5A8 DEFINE_SHOW_BIGNUM(result2->y);//6BCCE490 61B56118 B4EC79A9 15B6A102 B8E94A1D 07571C97 5A660947 57B35F6B DEFINE_SHOW_BIGNUM(result->x); DEFINE_SHOW_BIGNUM(result->y); xy_ecpoint_add_xy_ecpoint(result, result1, result2, ecp); DEFINE_SHOW_BIGNUM(result1->x); DEFINE_SHOW_BIGNUM(result1->y); DEFINE_SHOW_BIGNUM(result->x);//F6A687AB 5744D5CB BA1CF93D 8436416F 75C3AEC3 D762814D 565314AF F57A89F9 DEFINE_SHOW_BIGNUM(result->y);//F1B8EE05 41740565 491E4404 3DE53CF5 BBEDD613 33071260 DFC5783F 47A7B981 DEFINE_SHOW_BIGNUM(R);//0 DEFINE_SHOW_BIGNUM(result->x);//F6A687AB 5744D5CB BA1CF93D 8436416F 75C3AEC3 D762814D 565314AF F57A89F9 DEFINE_SHOW_BIGNUM(ecp->n);//FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123 BN_mod_add(R, e_bn, result->x, ecp->n, ecp->ctx); DEFINE_SHOW_BIGNUM(e_bn);//10D51CB9 0C0C0522 E94875A2 BEA7AB72 299EBE71 92E64EFE 0573B1C7 7110E5C9 这个也不一样 DEFINE_SHOW_BIGNUM(R);//077BA465 6350DAEE A3656EE0 42DDECE2 2D5E8DCA 4882CB20 080AD26E 2CB62E9F 就这不一样 DEFINE_SHOW_BIGNUM(result->x); DEFINE_SHOW_BIGNUM(ecp->n); sm2_bn2bin(R, sign->R, ecp->point_byte_length);DEFINE_SHOW_STRING(sign->R, ecp->point_byte_length); memcpy(singResulR, sign->R, ecp->point_byte_length); BN_free(e_bn);BN_free(t);BN_free(R);xy_ecpoint_free(result);xy_ecpoint_free(result1);xy_ecpoint_free(result2);xy_ecpoint_free(P_A);BN_free(r);BN_free(s);BN_free(P_x);BN_free(P_y);}
工程下载链接 https://pan.baidu.com/s/1qYoczak 没有密码
阅读全文
0 0
- 如何在iOS中使用SM2进行数字签名及校验
- Java中如何进行加密和数字签名
- 如何在Weblogic中校验及解释XML文件
- 国密SM2数字签名算法
- 如何在iOS设备中进行缓存
- iOS 如何在 VPN 中进行定位
- 如何在pdf中设置数字签名
- 如何在项目中应用数字签名技术
- 在Eclipse的Web项目中java里面使用ant进行数字签名步骤详解
- jsf中如何进行数据校验
- jsf中如何进行数据校验
- 如何使用Ajax进行登录校验
- 在ios中调用C语言的国密算法SM2以替换RSA
- IE中伪类:hover的使用及BUG,以及如何在IE6中进行修正(CSS)
- 在golang中如何使用rating-input来进行打分及评价
- 关于在applet中对jar包进行数字签名问题.
- SM2数字签名算法java实现
- Android应用开发中如何使用RSA加密算法对数据进行校验
- [译]图像分类:数据驱动方法、K-最近邻、train/val/test分离 (1)
- 金融企业软件测试中心筹备书-软件度量篇
- 变量提升的思考
- aop的理解
- 由异步回调引发的线程/进程“血案”
- 如何在iOS中使用SM2进行数字签名及校验
- 学生信息管理系统-GUI
- rocketmq
- 组合-聚合,关联-依赖
- unity 在移动平台中,文件操作路径详解
- 两个CPU核分配任务问题
- Linux 搭建hexo博客
- 分解质因数
- Java工程读取resources中资源文件路径问题