谈谈PBOC3.0中使用的国密SM2算法
转载请注明出处
http://blog.csdn.net/pony_maggie/article/details/39780825
作者:小马
一 知识准备
SM2是国密局推出的一种他们自己说具有自主知识产权的非对称商用password算法。本身是基于ECC椭圆曲线算法的。所以要讲sm2, 先要弄懂ECC。
全然理解ECC算法须要一定的数学功底。由于涉及到射影平面坐标系,齐次方程求解, 曲线的运算规则等概念。
这里不做过多的数学分析(主要是我自己也没有全然整明确)。
想要深入了解ECC的我推荐网名为ZMWorm 的大牛在多年前写的<<椭圆曲线ECC加密算法入门介绍>>。此人是早年看雪论坛中的一个版主,对算法和password学非常有研究。
本篇的主旨还是希望能以简单通俗的语言,讲清楚PBOC3.0认证过程中,所用到的SM2的相关概念,包含它的实现,使用等。
1 椭圆曲线究竟是什么样的
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcG9ueV9tYWdnaWU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
图1
图2
上面是两个不同椭圆曲线在坐标系中的几何表示, 只是这个坐标系不是二维坐标系,而是射影坐标系。能够用空间思维想像一下(可是注意不是三维坐标系), 打个例如,你晚上站在一个路灯前面,地上有你的影子,你本身是在一个二维坐标系(把你想像成一个纸片),和你的影子一起构成一个射影坐标系。
曲线的每个点, 用三个參量表示, (X,Y,Z)。我们知道在二维坐标系里的每个图形都遵循一个方程,比方直接的二元一次方程是y=kx+b, 圆的方程是(x-a)2+(y-b)2=r2, 椭圆曲线在射影坐标系里也有自己的定义:
Y2Z+a1XYZ+a3YZ2=X3+a2X2Z+a4XZ2+a6Z3
全部椭圆曲线上的点都满足上述方程。a1,a2,a3,a4,a6是系数,决定曲线的形状和位置。
二维坐标和射影坐标有一个相应关系。即x=X/Z, y=Y/Z, 这样就能够把上面的方程转成普通的二维坐标系方程:
y2+a1xy+a3y= x3+a2x2+a4x+a6
2 离散的椭圆曲线
上面的坐标系都是基于实数的,椭圆曲线看起来都是平滑的,假设我们限制曲线的点都必须是整数。曲线就变成离散的了。如图3所看到的:
图3
再进一步限制。要求整数必须大于0, 小于某个大整数P, 这样就形成了一个有限域Fp.然后我们在这个有限域里定义一些点与点之间的加减乘除运算规则。比方A点加B点得到C点(记做A+B≡C (mod p))。或者A点乘以n得到K点(记做A×n≡K (mod p))。
至于详细规则细节能够不用关心,仅仅要知道有这种操作就可以。
选一条曲线,比方
y2=x3+ax+b
把它定义在Fp上, 要求a,b满足:
4a3+27b2≠0 (mod p)
我们把这种曲线记为Ep(a,b)
加解密是基于这种数学难题,K=kG,当中 K,G为Ep(a,b)上的点,k是整数,小于G点(注意区分。不是我们寻常说的那个意思)的阶(不用关心什么是点的阶)。给定k和G,计算K非常easy;但给定K和G,求k就困难了。
这样。G就叫做基点。k是私钥。K是公钥。
最后总结。描写叙述一条Fp上的椭圆曲线,有六个參量:
T=(p,a,b,G,n,h)。
p 、a 、b 用来确定一条椭圆曲线,
G为基点。
n为点G的阶。
h 是椭圆曲线上全部点的个数m与n相除的整数部分)
知识准备阶段知道这么多就能够了。
二 SM2在PBOC认证中的使用
1 签名和验签的原理
前面提到依据系数的不同,ECC曲线能够有非常多,SM2使用当中一种,这就表明它的曲线方程,以及前面说到的六个參量都是固定的。
依据国密局给出的规范定义例如以下:
y2=x3+ax+b p=FFFFFFFE FFFFFFFFFFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
a=FFFFFFFE FFFFFFFFFFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC
b=28E9FA9E 9D9F5E344D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93
n=FFFFFFFE FFFFFFFFFFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123
Gx=32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7
Gy=BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0
这里easy引起一个误解,会觉得參数都固定了,公私钥是不是仅仅能有一对?当然不是,注意前面提到的K=kG的模型,K才是公钥,所以公钥事实上是曲线在离散坐标系中,满足条件的一个曲线上的点。能够有非常多个。另外, 从这几个參量能够获知PBOC 3.0的公钥长度都是256位。
基于这样的离散椭圆曲线原理的SM2算法一般有三种使用方法。签名验签。加解密, 密钥交换。PBOC 3.0中的脱机数据认证仅仅用到签名验签的功能。
终端关心的是怎样验签,卡片则要考虑怎样实现生成签名。
2 基于openssl实现sm2
这里给出一个基于openssl的sm2实现, 假设不了解openssl,能够先搜索一下相关知识,这里不解说。
openssl已经实现ECC算法接口,也就是核心已经有了。实现sm2事实上并不难,关键是理解它里面各种接口怎样使用。以下就分析一个终端验签的sm2实现。另外须要说明这里给出的仅仅是代码片段。仅供理解用。
函数接口
int SM2_Verify(BYTE* Px,BYTE* Py, BYTE* DataIn,DWORD DataLen, BYTE* sigrs)
前两个參数是K的坐标值,也就是公钥。
Datain和datalen各自是明文数据和其长度,最后一个參数是待验证的签名。
曲线的參数常量定义例如以下:
////////////////////////////////////////////////////////////////
static const char *group_p ="FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF";
static const char *group_a ="FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC";
static const char *group_b ="28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93";
static const char *group_Gx ="32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7";
static const char *group_Gy ="BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0";
static const char *group_n = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123";
static const char *ENTL_ID ="008031323334353637383132333435363738";
#define SM2_KEY_LENGTH 32 //256位曲线
////////////////////////////////////////////////////////////////
ENTL_ID是pboc规范中指定的用于SM3产生摘要的报文头数据。
strcpy(szBuff, ENTL_ID);
strcat(szBuff,group_a);
strcat(szBuff,group_b);
strcat(szBuff,group_Gx);
strcat(szBuff,group_Gy);
AscToBcd(szDataForDigest,(unsigned char *)szBuff, nLen); …. SM3(szDataForDigest,nLen+SM2_KEY_LENGTH*2, digestZA); memcpy(szDataForDigest,digestZA, ECC_LENGTH);
memcpy(szDataForDigest+ECC_LENGTH,DataIn, DataLen); SM3(szDataForDigest,DataLen+ECC_LENGTH, digestH);
第一步,对上述数据用sm3做摘要,摘要的结果与数据拼接后再做摘要。
p = BN_new();
a = BN_new();
b = BN_new();
group = EC_GROUP_new(EC_GFp_mont_method()); BN_hex2bn(&p, group_p))
BN_hex2bn(&a, group_a))
BN_hex2bn(&b, group_b))
这里是把定义的曲线常量转换成大数表式,这样才干使用openssl中的接口。
Group是ECC中的曲线组,它是ECC算法的核心。为什么这么说呢? 由于这个group里的全部字段就确定了曲线的全部信息, 后面会看到,这里仅仅是用EC_GROUP_new生成一个空的group, 然后由p,a,b等參数来填充group, 再以这个group为基础去生成曲线上的点。
if (!EC_GROUP_set_curve_GFp(group, p, a, b,ctx))
{
gotoerr_process;
} P = EC_POINT_new(group);
Q = EC_POINT_new(group);
R = EC_POINT_new(group);
if (!P || !Q || !R)
{
gotoerr_process;
}
这一段就确定了group的全部信息。而且依据group生成三个曲线上的点(点一定在曲线上,这个非常重要)。
<span style="white-space:pre"> </span>x = BN_new();
y= BN_new();
z= BN_new();
if(!x || !y || !z)
{
gotoerr_process;
} //Gx
if(!BN_hex2bn(&x, group_Gx))
{
gotoerr_process;
} if(!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx))
{
gotoerr_process;
} if(!BN_hex2bn(&z, group_n))
{
gotoerr_process;
}
if(!EC_GROUP_set_generator(group, P, z, BN_value_one()))
{
gotoerr_process;
} if(!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))
{
gotoerr_process;
}
这一段首先是设置n到group, n前面讲过,是曲线的阶。另外就是由G点坐标x,y确定点P,这里我事实上也有点不太明确。G点坐标y本来就是已知的,为什么要再通过曲线变换表式生成y,是不是想要对照前面的group信息是否正确?仅仅是为了校验?
if ((eckey = EC_KEY_new()) == NULL)
{
gotoerr_process;
}
if(EC_KEY_set_group(eckey, group) == 0)
{
gotoerr_process;
} EC_KEY_set_public_key(eckey, P);
if(!EC_KEY_check_key(eckey))
{
gotoerr_process;
} if(SM2_do_verify(1, digestH, SM2_KEY_LENGTH, signature, sig_len, eckey) != 1)
{
gotoerr_process;
}
这段比較好理解,生成公钥eckey,并由eckey终于验签。
验签的运行函数sm2_do_verify有点复杂,这里不做过多的解释(事实上是我解释不清楚, 哇哈哈),在一个国外的站点上找到一个比較好的描写叙述,拿过来用用。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcG9ueV9tYWdnaWU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
3 脱机数据认证使用sm2的详细流程
我如果看这篇文章的人对PBOC 2.0中基于RSA国际算法的脱机数据认证流程已经比較了解。相关概念不再过多描写叙述。重点关注二者的差异性。
另外,简单说一下sm3,由于以下会用到。sm3是一个类似hash的杂凑算法,即给定一个输入(一般非常长),产生一个固定长度的输出(sm3是32个字节,hash是20个字节)。它有两个特点:
1 不可逆性。即无法由输出推导出输入。
2 不同的输入,产生不同的输出。
以下就拿终端SDA认证卡片来看看sm2怎样在pboc中使用的。
首先。发卡行公钥等数据(还包含公钥,算法标识,有效期等信息)被CA私钥签名(注意不是加密)生成发卡行公钥证书,这个证书会个人化到ic卡中。这些数据例如以下图所看到的:
图4
签名事实上就是对这个表里的数据做一系列运算,终于生成一个64字节的数据,分别由各32字节的r和s拼接而成(r和s仅仅是个符号而已,没有特别意思)。这64字节的签名拼接到图4后面就是发卡行公钥证书。
这里与国际算法的公钥证书就有明显的差别了。国际算法证书是密文的。发卡行公钥用rsa加密。
而国密的公钥证书全然是明文。用数据举例,以下这些数据来自pboc3.0的卡片送检指南,就是检測时要求个人化到卡里的数据。
【发卡行公钥】 :
173A31DD681C6F8FE3BA6C354AD3924A4ADFD15EB0581BC1B37A1EB1C88DA29B47155F62FCF4CCCD201B134351A049D77E81F6A6C66E9CB32664F41348DA11F 【CA哈希值】(r||s) :
3499A2A0A7FED8F74F119B416FF728BA98EF0A32A36BCCB8D0110623D466425CA44C68F8E49121D9BFA9484CAEF9B476C5EB576D1A8DD6BC4A0986AF4134ABAF 【Tag_90 】(发卡行公钥证书) :
1262280001122000000204001140173A31DD681C6F8FE3BA6C354AD3924A4ADFD15EB0581BC1B37A1EB1C88DA29B47155F62FCF4CCCD201B134351A049D77E86A6C66E9CB32664F41348DA11F63499A2A0A7FED8F74F119B416FF728BA98EF0A32A36BCCB8D0110623D466425CA44C68F8E49121D9BFA9484CAEF9B476C5E56D1A8DD6BC4A0986AF4134ABAF
能够自己的解析一下,看看是否和上面表格中的数据一致, 而且都是明文。
终端在读记录阶段获取发卡行公钥证书。国际算法须要用rsa公钥解密整个证书,然后验证hash,通过后取出发卡行公钥。而国密算法,终端仅仅要用sm2公钥验64字节的签名,通过后直接取明文发卡行公钥,所以国密的验签的动作事实上就相当于国际里的rsa解密和hash对照两个动作。
接着终端进行静态数据签名的验证,情况类似,对于国密,这些数据都是明文形式,后面拼接64字节的sm2签名,这64字节是用发卡行私钥对明文数据签名得到的。终端要做的就是拿刚刚获取的发卡行公钥对这64字节数据验证就可以,验证通过就表示SDA通过。
四 PBOC为什么要选择国密
首先从技术角度,实现相同的计算复杂度,ECC的计算量相对RSA较小,所以效率高。RSA如今在不断的添加模长,眼下都用到了2048位。并非说如今一定要用2048位才是安全的,仅仅是它的安全性更高,破解难度更大,这个要综合考虑,位数高也意味着成本高。
有些不差钱的大公司比方谷歌就已经未雨绸缪的把2048位用在了它们的gmail邮箱服务中。PBOC3.0 认证中眼下仅仅用到1984位。事实上也是相对安全的。
只是这个观点眼下还存在争议。
前段时间在清华大学听了一个关于password算法的课,清华有个教授觉得sm2并不见得比rsa更高级,仅仅是sm2的原理比rsa难理解,所以大部分人觉得它会相对安全些。一旦椭圆曲线被大家研究透了。sm2的光环也可能就此褪去。当然这个也是他个人的观点。
另外一个因素,要从国家战略的角度考虑,RSA之前一直被传与美国安全局合作,在算法中增加后门。这样的事是宁可信其有的。
国密算法咱起码是自己研发的东西,全部的过程细节都一清二楚, 不用担收后门的事情。
央行如今非常重视国产安全芯片的推进工作,前些天央行的李晓枫还公开强调未来金融IC卡芯片要国产化,国密算法是当中非常关键的一步。
未来国产芯片加国密算法,才会有真正自主, 安全的国产金融IC卡产品。
谈谈PBOC3.0中使用的国密SM2算法的更多相关文章
- java 解析国密SM2算法证书
首先说明用Java自带的解析x509证书类,是不能解析sm2算法的证书,执行会抛出异常. 用开源库bouncycastle能够解析.详细代码 private byte[] getCSPK(byte[] ...
- 推荐一款能支持国密SM2浏览器——密信浏览器
密信浏览器( MeSince Browser )是基于Chromium开源项目开发的国密安全浏览器,支持国密算法和国密SSL证书,同时也支持国际算法及全球信任SSL证书:密信浏览器使用界面清新,干净. ...
- Linux实现树莓派3B的国密SM9算法交叉编译——(三)国密SM9算法实现
先参考这篇文章 Linux实现树莓派3B的国密SM9算法交叉编译——(二)miracl库的测试与静态库的生成 进行miracl库的交叉编译测试,并生成miracl静态链接库. 这篇文章主要介绍基于mi ...
- Linux实现树莓派3B的国密SM9算法交叉编译——(二)miracl库的测试与静态库的生成
先参考这篇文章 Linux实现树莓派3B的国密SM9算法交叉编译——(一)环境部署.简单测试与eclipse工程项目测试 部署好环境,并简单测试交叉编译环境是否安装成功,最后实现在Eclipse上进行 ...
- 一个支持国密SM2/SM3/SM4/SM9/ZUC/SSL的密码工具箱
转:https://blog.csdn.net/xuq09/article/details/91815366 The GmSSL Project网址:http://gmssl.org/docs/qui ...
- bouncycastle 国密SM2 API的使用
摘要:本文不对SM2做过多的介绍,主要介绍java bouncycastle库关于SM2的相关API的使用及注意事项 1. SM2 签名: 注意: 1)签名格式ASN1(描述了一种对数据进行表示.编码 ...
- Java国密相关算法(bouncycastle)
公用类算法: PCIKeyPair.java /** * @Author: dzy * @Date: 2018/9/27 14:18 * @Describe: 公私钥对 */ @Data @AllAr ...
- 国密SM3算法在linux和windows平台结果不一致问题
什么是sm3,是一种类似于sha256的哈希算法,是咱们国家的哈希标准算法: 最近在使用sm3算法时,同样的一份数据,调用同样的sm3接口,发现得到的结果是不一样的: 那么在应用过的过程中,如果同样的 ...
- 国密SM9算法C++实现(Linux)
首先参考 Linux下编译并使用miracl密码库 该博文在linux下编译Miracl库. 编译完了,自然是要用的,下面介绍两种在C程序中使用miracl库的方法. 方法一: 1. 源码编译完后的必 ...
随机推荐
- PTA 数据结构 银行业务队列简单模拟
仅供参考,请勿粘贴 设某银行有A.B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 -- 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客.给定到达银行的顾客序列,请按业务完 ...
- Java多线程Master-Worker模式
Java多线程Master-Worker模式,多适用于需要大量重复工作的场景中. 例如:使用Master-Worker计算0到100所有数字的立方的和 1.Master接收到100个任务,每个任务需要 ...
- rewirte 规则
Nginx Rewrite Rewirte 规则也称为规则重写,主要功能是实现浏览器访问 HTTP URL 的跳转,其正则 表达式是基于 Perl 语言.通常而言,几乎所有的 WEB 服务器均可以支持 ...
- SqlServer 数据库附加问题:不是主数据库文件
一.前言 今天公司要切换数据库服务器,数据库文件大于2G,结果再附加到另一服务器的数据库里面,就产生了一个问题.如下: 标题:Microsoft SQL Server Management Studi ...
- WPF字符串中的换行符
<sys:String x:Key="NewUpdateWillShow" xml:space="preserve">第一行 第二行 </sy ...
- shell 备份脚本
[root@izwz9hmoz58gvtu0ldpm0iz ~]# cat /usr/local/aaaa/shell_script/Mysql_Dump_LJY.sh #! /bin/bash to ...
- phpcms v9 前台getshell脚本
phpcms v9 前台getshell脚本 用法:python phpcmsv9getshell.py http://baidu.com # -*- coding:utf-8 -*- ''' --- ...
- 查看Page结构
SQL Server存储数据的基本单元是Page,每一个Page的大小是8KB,数据文件是由Page构成的.在同一个数据库上,每一个Page都有一个唯一的资源标识,标识符由三部分组成:db_id,fi ...
- 在本地搭建play-with-docker
安装play-with-docker 官方Github地址 https://github.com/play-with-docker/play-with-docker 本人Github地址 https: ...
- MongoDB一:入门(安装与配置)
一.简介 MongoDB 是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. mongoDB MongoDB 是一个介于关系数据库和非关系数据库 ...