版本人员时间升级内容课程目的◦了解国密算法的算法原理◦了解SM2、SM3、SM4的算法原理◦了解国密卡片相关API目标人员◦移动金融初级开发人员前置课程◦RSA密钥体系◦DES密钥体系基本知识对称加密算法SM2非对称加密算法SM4摘要算法SM3定义国密即国家密码局认定的国产密码算法,即商用密码,主要完成加密、解密、签名、验签、摘要等操作。常用国密算法种类算法类型密钥长度输入数据要求输出数据特征SM2非对称加密算法公钥64字节,私钥32字节。长度小于(2^32-1)*32=137,438,953,440字节(大约1374亿多)。输出长度是明文长度+96,有随机数参数,每次密文不同。SM3摘要算法--无要求。固定长度,32字节。SM4对称加密算法16字节分组长度16字节,需要填充到16字节整数倍。有CBC和ECB两种模式,CBC需要设定初始值。长度为16字节整数倍。国密算法还有SM1、SM7、SSF33、祖冲之密码对称加密算法,SM9非对称加密算法。国密算法与其他算法比较非对称加密算法SM2与RSA比较国密算法与其他算法比较SM2与RSA算法的一些统计数据RSA密钥强度(长度)SM2密钥强度(长度)破解时间(年)521比特106比特104(已破解)768比特132比特108(已破解)1024比特160比特10112048比特210比特1020国密算法与其他算法比较SM2与RSA算法的一些统计数据算法签名速度验签速度1024RSA2792次/秒51224次/秒2048RSA455次/秒15122次/秒256SM24095次/秒871次/秒国密算法与其他算法比较SM4与DES较从算法上看,国产SM4算法在计算过程中增加非线性变换,理论上能大大提高其算法的安全性,并且由专业机构进行了密码分析,民间也对21轮SM4进行了差分密码分析,结论均为安全性较高。国密卡实现API类层次图classjava.lang.Object◦classcom.guomi.GMCipher◦classcom.guomi.GMKeyBuilder◦classcom.guomi.GMKeyPair◦classcom.guomi.GMMessageDigest◦classcom.guomi.GMSignature◦classcom.guomi.GMCipherExtend◦classcom.guomi.GMSM2KeyExchange国密卡实现的API接口interfacejavacard.security.Key◦interfacejavacard.security.SecretKeyinterfacecom.guomi.SM1Keyinterfacecom.guomi.SM4Keyinterfacecom.guomi.SM7Keyinterfacecom.guomi.SSF33Key◦interfacejavacard.security.PrivateKeyinterfacecom.guomi.SM2PrivateKey◦interfacejavacard.security.PublicKeyinterfacecom.guomi.SM2PublicKey国密卡实现的API接口interfacecom.unionpay.guomi.SM2Key◦interfacecom.guomi.SM2PrivateKey◦interfacecom.guomi.SM2PublicKey目录算法原理加密解密签名验签算法原理国密SM2规定椭圆曲线参数(固定值,256比特)◦p:FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF◦a:FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC◦b:28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93◦n:FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123◦gx:32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7◦gy:BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0各个参数意义如下椭圆曲线方程:y2=x3+ax+b,把它定义在Fp上,要求a,b满足:4a3+27b2≠0(modp)那么,p、a、b用来确定一条椭圆曲线(确切来说应该是有限域Fp),G(gx,gy)为基点,n为点G的阶,另外,还有一个非必要参数h,是椭圆曲线上所有点的个数m与n相除的整数部分;加密SM2公私玥结构、◦SM2公私玥关系P=d*G或者(x,y)=d*(gx,gy),即公钥P是基点G的d倍点。其中,P为公钥,坐标表示为(x,y),d为私钥,G为基点,坐标(gx,gy),‘*’为离散椭圆曲线坐标系中的乘法运算。长度举例SM2公钥64字节,包括x分量和y分量6C7D9D212ED9A5B43659402F07696F7026AE2ADB874D9BDC2D4DC47D883B6AEE8FC2FA7668EFD664E0876B21B1C6202551978331C59259489E5B13F941E1EA95SM2私钥32字节38DAF6D271322AF0AFEE399DEEF28D18B51CD8388BF78F4E78B943E7436181A4离散域加法及多倍点图解公私玥SM2公私玥对生成◦JavaCardGMKeyPairdGM_KeyPair=null;SM2PublicKeydSM2pubkey=null;SM2PrivateKeydSM2prikey=null;dGM_KeyPair=newGMKeyPair(GMKeyPair.ALG_SM2_FP,GMKeyBuilder.LENGTH_SM2_FP_256);dSM2pubkey=(SM2PublicKey)GMKeyBuilder.buildKey(GMKeyBuilder.TYPE_SM2_PUBLIC,GMKeyBuilder.LENGTH_SM2_FP_256,true);dSM2prikey=(SM2PrivateKey)GMKeyBuilder.buildKey(GMKeyBuilder.TYPE_SM2_PRIVATE,GMKeyBuilder.LENGTH_SM2_FP_256,true);dGM_KeyPair.genSM2KeyPair();dSM2prikey=(SM2PrivateKey)dGM_KeyPair.getPrivate();dSM2pubkey=(SM2PublicKey)dGM_KeyPair.getPublic();公私玥SM2公私玥对生成◦JavaEEAsymmetricCipherKeyPairkeyPair=ecKeyPairGenerator.generateKeyPair();ECPrivateKeyParameterspriKey=(ECPrivateKeyParameters)keyPair.getPrivate();ECPublicKeyParameterspubKey=(ECPublicKeyParameters)keyPair.getPublic();BigIntegerbiD=priKey.getD();//私钥BigIntegerbiX=pubKey.getQ().getX().toBigInteger();//公钥X分量BigIntegerbiY=pubKey.getQ().getY().toBigInteger();//公钥Y分量加密明文结构◦SM2加密算法对明文数据不需要填充。◦SM2加密算法要求明文长度小于(2^32-1)*32字节。注:RSA算法中,明文长度要求小于模长。加密完整密文结构字段名称解析长度XCoordinate离散椭圆曲线上随机点的x分量32字节YCoordinate离散椭圆曲线上随机点的y分量32字节HASH哈希值,32字节CipherText纯密文与明文长度一致注:SM2算法中,由于需要随机选取点参与密文计算,故相同的明文及密钥,在不同的加密过程中,密文也不相同,与RSA算法不同。加密加密步骤◦加密输入数据:源数据(M)、SM2公钥SM2Publickey(包括公钥分量x、公钥分量y)。◦通过SM2公钥加密算法,计算完整密文。加密SM2加密代码实现◦JavaCardCipherdGM_Cipher=GMCipher.getInstance(GMCipher.ALG_SM2_WITH_SM3_NOPAD,false);dGM_Cipher.init(dSM2pubkey,Cipher.MODE_ENCRYPT);shortreslen=dGM_Cipher.doFinal(debugdata,(short)0,(short)debugdata.length,buf,(short)0);加密SM2加密代码实现◦JavaEESM2sm2=SM2.getInstance();Ciphercipher=newCipher();ECPointuserKey=sm2.getUserKey(x,y);//随机生成公钥分量,c1.x、c1.y。cipher.encrypt(data)ECPointc1=cipher.init_enc(sm2,userKey);byte[]xy=c1.getEncoded();byte[]thash=necipher.doFinal(thash);//计算HASHwbyte[32];System.out.println(allciphertext=+Utils.toHexStringNoBlank(xy).substring(2,130)+Utils.toHexStringNoBlank(thash)+Utils.toHexStringNoBlank(data));解密解密步骤◦输入数据:密文(C)、SM2私钥SM2prikey。◦计算出明文M,并校验HASH。解密解密代码实现◦JavaCardCipherdGM_Cipher=GMCipher.getInstance(GMCipher.ALG_SM2_WITH_SM3_NOPAD,false);dGM_Cipher.init(dSM2prikey,Cipher.MODE_ENCRYPT);Shortreslen=dGM_Cipher.doFinal(buf,ISO7816.OFFSET_CDATA,reslen,buf,(short)0);解密解密代码实现◦JavaEE//分解密文,得到随机取的点x、y分量,hash值,纯密文。//椭圆曲线上随机取的点pointECPointpoint=SM2.getInstance().ecc_curve.decodePoint(c1);cipher.init_dec(priKey,point);cipher.decrypt(pureciphertext);cipher.doFinal(c3_);//使用解密的明文计算的hash,C3_.StringC3_=Utils.toHexStringNoBlank(c3_);//密文中恢复的hash,C3.StringC3=Utils.toHexStringNoBlank(c3);if(!C3_.equals(C3)){System.out.println(未通过C3校验,解密失败\nC3=+C3+\nC3_=+C3_);return;}签名私钥签名值结构字段解释长度R签名值的第一部分32字节S签名值的第二部分32字节签名