springboot使用国产加密算法方式,sm2和sm3加解密demo
作者:yy1209357299
需求
前后端交互的加解密算法,要求使用国产的
1、SM1分组密码算法
SM1是由国家密码管理局编制的一种商用密码分组标准对称算法,分组长度和密钥长度均为128位,算法的安全保密强度及相关软硬件实现性能与AES算法相当,目前该算法尚未公开,仅以IP核的形式存在于芯片中,调用该算法时,需要通过加密芯片的接口进行调用。
2、*SM2公钥密码算法
SM2算法是国家密码据于2010年12月17日发布的国密标准椭圆曲线加密算法,是一种基于ECC算法的非对称加密算法,SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。
SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,对于一般椭圆曲线的离散对数问题,目前只存在指数级计算复杂度的求解方法。
与大数分解问题及有限域上离散对数问题相比,椭圆曲线离散对数问题的求解难度要大得多。
因此,在相同安全程度要求下,椭圆曲线密码较其他公钥密码所需的秘钥规模要小得多。
相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高。
其加密强度为256位,密钥长度短,安全程度高,可用于数字签名、密钥交换、公钥加密。
3、*SM3密码杂凑算法
SM3是我国采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。
相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。
据国家密码管理局表示,其安全性及效率与SHA-256相当,也叫密码杂凑算法,属于哈希(摘要)算法的一种,功能与MD5,SHA-1相同。
对长度小于264比特的消息m,经过填充、压缩,生成256位杂凑值,和SM2算法一起被公布,该算法位不可逆的算法。
在商用密码体系中,SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,可满足多种密码应用的安全需求,算法已公开。
4、*SM4分组密码算法
SM4是国家密码管理局发布的分组密码算法,于2012年3月正式公布。
与DES和AES算法类似,SM4是一种分组密码算法。其分组长度为128bit,密钥长度也为128bit。
SM4算法加/解密算法是对合运算,只是使用轮密钥相反,其中解密轮密钥是加密轮密钥的逆序。
加密算法与密钥扩展算法均采用32轮非线性迭代结构(Feistel),以字(32位)为单位进行加密运算,每一次迭代运算均为一轮变换函数F。
目前主要用于无线局域网产品。
方案
使用场景:前后端交互使用sm2,后端存储密码时使用sm3
1、pom依赖
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.60</version> </dependency>
2、demo示例
public static void main(String[] args) throws InvalidCipherTextException { System.out.println("sm2测试开始-----------"); X9ECParameters sm2EcParameters = GMNamedCurves.getByName("sm2p256v1"); ECDomainParameters domainParameters = new ECDomainParameters(sm2EcParameters.getCurve(),sm2EcParameters.getG(),sm2EcParameters.getN()); ECKeyPairGenerator keyPairGenerator =new ECKeyPairGenerator(); try { keyPairGenerator.init(new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG"))); AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair(); //私钥 BigInteger privateKey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD(); String privateKeyHex = privateKey.toString(16); System.out.println("私钥:" + privateKeyHex); //公钥 ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ(); String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false)); System.out.println("公钥:" + publicKeyHex); String str = SM2Util.encrypt("test",publicKeyHex); System.out.println("加密结果:"+str); try{ String res = SM2Util.decrypt(str,privateKeyHex); System.out.println("解密结果:"+res); }catch (Exception e){ e.printStackTrace(); } System.out.println("sm2测试结束-----------"); System.out.println("sm3测试开始-----------"); String sm3 = SM3Util.sm3Sign("test"); System.out.println("sm3加密结果"+sm3); if(SM3Util.sm3Verify("test",sm3)){ System.out.println("sm3验证成功"); }else { System.out.println("sm3验证失败"); } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } }
3、结果
sm2测试开始-----------
私钥:bdda9f26ae5884e3f5410902aec78cab6c3f4a7c9d9578e6a9c60ae977d6d645
公钥:041870142d71f518ce9bd6458b4b41b4d49e7fbfd9a14440eb49ed9bbb352e72739d2e2369722ba381db2a7add5093c7a976df49496cb5c08a56e87db877f4e866
加密结果:0445fd5bce247f30cd507314830f57d3278dfdfab3e8fdc6acb93c60a3a4b6bbc09150c065153389d7b0c3581a0a0fd5c3ffe59ed53855a289a98ce9705a5230b752aa8535980ba08db6319eef0f3c1140ccd3d0849f0c78a4478189c1736de07b27254794929c9de9
解密结果:test
sm2测试结束-----------
sm3测试开始-----------
sm3加密结果55e12e91650d2fec56ec74e1d3e4ddbfce2ef3a65890c2a19ecf88a307e76a23
sm3验证成功
4、前端加密
const sm2 = require('sm-crypto').sm2 const cipherMode = 0 // 1 - C1C3C2,0 - C1C2C3,默认为1,这里用0
加密
let base = Base64.encode(msgString); let encryptData = sm2.doEncrypt(base, publicKey, cipherMode) // 加密结果 conso.log("加密结果:",encryptData);
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。