JAVA-国密算法SM3和SM4应用Example
参考资料:
https://baijiahao.baidu.com/s?id=1629915330021466224&wfr=spider&for=pc
https://github.com/chenliwu/gmhelper
Maven引入加密算法库
<!-- 国密算法 -->
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.65</version>
</dependency>
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.65</version>
</dependency>
<!-- 国密算法 -->
SM3(杂凑算法)
1、SM3为杂凑算法(消息摘要,也称为散列函数)。可以用MD5作为对比理解。该算法已公开。校验结果为256位。
2、SM3杂凑算法是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性。SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。
3、SM3用于生成消息摘要,应用于数字签名的生成和验证。
SM3工具类代码
public class SM3Utils {static {Security.addProvider(new BouncyCastleProvider());}/*** 计算SM3摘要值** @param srcData 原文* @return 摘要值,对于SM3算法来说是32字节*/public static byte[] hash(byte[] srcData) {SM3Digest digest = new SM3Digest();digest.update(srcData, 0, srcData.length);byte[] hash = new byte[digest.getDigestSize()];digest.doFinal(hash, 0);return hash;}/*** 验证摘要** @param srcData 原文* @param sm3Hash 摘要值* @return 返回true标识验证成功,false标识验证失败*/public static boolean verify(byte[] srcData, byte[] sm3Hash) {byte[] newHash = hash(srcData);if (Arrays.equals(newHash, sm3Hash)) {return true;} else {return false;}}/*** 计算SM3 Mac值** @param key key值,可以是任意长度的字节数组* @param srcData 原文* @return Mac值,对于HMac-SM3来说是32字节*/public static byte[] hmac(byte[] key, byte[] srcData) {KeyParameter keyParameter = new KeyParameter(key);SM3Digest digest = new SM3Digest();HMac mac = new HMac(digest);mac.init(keyParameter);mac.update(srcData, 0, srcData.length);byte[] result = new byte[mac.getMacSize()];mac.doFinal(result, 0);return result;}
}
SM3单测代码
public class SM3UtilsTest {public static final String KEY = "1234567812345678";public static final String CHARSET_UTF8 = StandardCharsets.UTF_8.name();@Testpublic void testGenerateHash() throws Exception {String data = "测试SM3杂凑算法";// 生成消息摘要 消息摘要=SM3(原文)byte[] signByte = SM3Utils.hash(data.getBytes(CHARSET_UTF8));String signBase64String = Base64.toBase64String(signByte);System.out.println("\n消息摘要 Base64 String:" + signBase64String);// 生成数字签名 数字签名 = SM3(原文+密钥)String digitalSign = Base64.toBase64String(SM3Utils.hash((data + KEY).getBytes(CHARSET_UTF8)));System.out.println("\n数字签名 Base64 String:" + digitalSign);}@Testpublic void testHashAndVerify() {try {String data = "SM3UtilsTest";byte[] hash = SM3Utils.hash(data.getBytes(CHARSET_UTF8));System.out.println("hash:" + Arrays.toString(hash));String hashBase64String = Base64.toBase64String(hash);System.out.println("SM3 Base64 String:\n" + hashBase64String);System.out.println("hash:\n" + Arrays.toString(Base64.decode(hashBase64String)));boolean flag = SM3Utils.verify(data.getBytes(CHARSET_UTF8), hash);System.out.println("验证结果:" + flag);System.out.println("======");Assert.assertEquals(true, flag);} catch (Exception ex) {ex.printStackTrace();}}}
运行结果:
消息摘要 Base64 String:+nNWZysGWq8yrqAUs1OUfVakiADNOrqgQf6tc3F08EM=
数字签名 Base64 String:9zQNDWGfGsNlN/12Dgu1TvuslfAJVkoU1TWnkUJR1qI=hash:[-48, -34, 61, -18, 35, 57, -55, 66, -72, 19, -117, -81, -7, -14, 57, -65, 85, 51, 16, 58, 36, -23, -108, 77, -27, -97, -27, 73, 88, -126, 15, -118]
SM3 Base64 String:
0N497iM5yUK4E4uv+fI5v1UzEDok6ZRN5Z/lSViCD4o=
hash:
[-48, -34, 61, -18, 35, 57, -55, 66, -72, 19, -117, -81, -7, -14, 57, -65, 85, 51, 16, 58, 36, -23, -108, 77, -27, -97, -27, 73, 88, -126, 15, -118]
验证结果:true
SM4(分组密码算法)
1、SM4 无线局域网标准的分组密码算法。对称加密,密钥长度和分组长度均为128位。
2、SM4分组密码算法是我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。
SM4工具类
public class SM4Utils {static {Security.addProvider(new BouncyCastleProvider());}public static final String ALGORITHM_NAME = "SM4";public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";public static final String ALGORITHM_NAME_ECB_NOPADDING = "SM4/ECB/NoPadding";public static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";public static final String ALGORITHM_NAME_CBC_NOPADDING = "SM4/CBC/NoPadding";/*** SM4算法目前只支持128位(即密钥16字节)*/public static final int DEFAULT_KEY_SIZE = 128;public static byte[] generateKey() throws NoSuchAlgorithmException, NoSuchProviderException {return generateKey(DEFAULT_KEY_SIZE);}public static byte[] generateKey(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException {KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);kg.init(keySize, new SecureRandom());return kg.generateKey().getEncoded();}public static byte[] encrypt_ECB_Padding(byte[] key, byte[] data)throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}public static byte[] decrypt_ECB_Padding(byte[] key, byte[] cipherText)throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);return cipher.doFinal(cipherText);}public static byte[] encrypt_ECB_NoPadding(byte[] key, byte[] data)throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_NOPADDING, Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}public static byte[] decrypt_ECB_NoPadding(byte[] key, byte[] cipherText)throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_NOPADDING, Cipher.DECRYPT_MODE, key);return cipher.doFinal(cipherText);}public static byte[] encrypt_CBC_Padding(byte[] key, byte[] iv, byte[] data)throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException,InvalidAlgorithmParameterException {Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.ENCRYPT_MODE, key, iv);return cipher.doFinal(data);}public static byte[] decrypt_CBC_Padding(byte[] key, byte[] iv, byte[] cipherText)throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,InvalidAlgorithmParameterException {Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.DECRYPT_MODE, key, iv);return cipher.doFinal(cipherText);}public static byte[] encrypt_CBC_NoPadding(byte[] key, byte[] iv, byte[] data)throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException,InvalidAlgorithmParameterException {Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.ENCRYPT_MODE, key, iv);return cipher.doFinal(data);}public static byte[] decrypt_CBC_NoPadding(byte[] key, byte[] iv, byte[] cipherText)throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,InvalidAlgorithmParameterException {Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.DECRYPT_MODE, key, iv);return cipher.doFinal(cipherText);}public static byte[] doCMac(byte[] key, byte[] data) throws NoSuchProviderException, NoSuchAlgorithmException,InvalidKeyException {Key keyObj = new SecretKeySpec(key, ALGORITHM_NAME);return doMac("SM4-CMAC", keyObj, data);}public static byte[] doGMac(byte[] key, byte[] iv, int tagLength, byte[] data) {org.bouncycastle.crypto.Mac mac = new GMac(new GCMBlockCipher(new SM4Engine()), tagLength * 8);return doMac(mac, key, iv, data);}/*** 默认使用PKCS7Padding/PKCS5Padding填充的CBCMAC** @param key* @param iv* @param data* @return*/public static byte[] doCBCMac(byte[] key, byte[] iv, byte[] data) {SM4Engine engine = new SM4Engine();org.bouncycastle.crypto.Mac mac = new CBCBlockCipherMac(engine, engine.getBlockSize() * 8, new PKCS7Padding());return doMac(mac, key, iv, data);}/*** @param key* @param iv* @param padding 可以传null,传null表示NoPadding,由调用方保证数据必须是BlockSize的整数倍* @param data* @return* @throws Exception*/public static byte[] doCBCMac(byte[] key, byte[] iv, BlockCipherPadding padding, byte[] data) throws Exception {SM4Engine engine = new SM4Engine();if (padding == null) {if (data.length % engine.getBlockSize() != 0) {throw new Exception("if no padding, data length must be multiple of SM4 BlockSize");}}org.bouncycastle.crypto.Mac mac = new CBCBlockCipherMac(engine, engine.getBlockSize() * 8, padding);return doMac(mac, key, iv, data);}private static byte[] doMac(org.bouncycastle.crypto.Mac mac, byte[] key, byte[] iv, byte[] data) {CipherParameters cipherParameters = new KeyParameter(key);mac.init(new ParametersWithIV(cipherParameters, iv));mac.update(data, 0, data.length);byte[] result = new byte[mac.getMacSize()];mac.doFinal(result, 0);return result;}private static byte[] doMac(String algorithmName, Key key, byte[] data) throws NoSuchProviderException,NoSuchAlgorithmException, InvalidKeyException {Mac mac = Mac.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);mac.init(key);mac.update(data);return mac.doFinal();}private static Cipher generateECBCipher(String algorithmName, int mode, byte[] key)throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,InvalidKeyException {Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);cipher.init(mode, sm4Key);return cipher;}private static Cipher generateCBCCipher(String algorithmName, int mode, byte[] key, byte[] iv)throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,NoSuchProviderException, NoSuchPaddingException {Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);cipher.init(mode, sm4Key, ivParameterSpec);return cipher;}
}
SM4单测代码
public class SM4UtilsTest {@Testpublic void testCustomKeySM4ECB() throws Exception {String charset = StandardCharsets.UTF_8.name();// SM4密钥长度分组长度128bit,因此密匙长度为16String myKey = "1234567812345678";String data = "SM4UtilsTest";byte[] myKeyBytes = myKey.getBytes(charset);byte[] encryptedBytes = SM4Utils.encrypt_ECB_Padding(myKeyBytes, data.getBytes(charset));String encryptedHexString = ByteUtils.toHexString(encryptedBytes);System.out.println("ECB加密后的数据HexString:" + encryptedHexString);byte[] decryptedBytes = SM4Utils.decrypt_ECB_Padding(myKeyBytes, ByteUtils.fromHexString(encryptedHexString));System.out.println("ECB解密后的数据:" + new String(decryptedBytes, charset));}@Testpublic void testCustomKeySM4CBC() throws Exception {String charset = StandardCharsets.UTF_8.name();// SM4密钥长度分组长度128bit,因此密匙长度为16String myKey = "1234567812345678";String myIv = "8765432187654321";String data = "SM4UtilsTest";byte[] myKeyBytes = myKey.getBytes(charset);byte[] myIvBytes = myIv.getBytes(charset);byte[] encryptedBytes = SM4Utils.encrypt_CBC_Padding(myKeyBytes, myIvBytes, data.getBytes(charset));String encryptedHexString = ByteUtils.toHexString(encryptedBytes);System.out.println("CBC加密后的数据HexString:" + encryptedHexString);byte[] decryptedBytes = SM4Utils.decrypt_CBC_Padding(myKeyBytes, myIvBytes, ByteUtils.fromHexString(encryptedHexString));System.out.println("CBC解密后的数据:" + new String(decryptedBytes, charset));}}
运行结果:
ECB加密后的数据HexString:a7df3e6b9332d09939677631db0a3dbc
ECB解密后的数据:SM4UtilsTestCBC加密后的数据HexString:81335cd7f2101b1786fa620afa595e11
CBC解密后的数据:SM4UtilsTest
JAVA-国密算法SM3和SM4应用Example相关推荐
- Java 国密算法 SM3 散列哈希使用
Java 国密算法 SM3 散列哈希使用 文章目录 Java 国密算法 SM3 散列哈希使用 引入依赖 计算散列哈希 引入依赖 <dependency><groupId>org ...
- 国密算法SM3与SM4简介与应用
点击上方蓝字可直接关注!方便下次阅读.如果对你有帮助,麻烦点个在看或点个赞,感谢~ 最近0基础在学习国密算法的相关应用,故此和大家分享下自己的一些经历. 程序平台: Ubuntu16.04 x64 ...
- php 国密算法,SM2,SM4,SM3,国密算法PHP版.rar
1 身份认证例子(htm5)\普通例子\网页驱动安装\SetUp.exe 7.23 MB 2017/8/10 18:21:12 2 身份认证例子(htm5)\自动登录安装包\自动登录安装包\SetUp ...
- 国密算法SM3(杂凑算法)
国家密码管理局关于发布<SM3密码杂凑算法>公告 SM3密码杂凑算法 JavaScript对本算法的一个实现:https://github.com/wcube/sm-crypto
- 国密算法 SM2公钥密码 SM3杂凑算法 SM4分组密码 python代码完整实现
包含SM2公钥密码.SM3杂凑算法和SM4分组密码的国密算法完整工具包完成了.此前分别发布过上述三个算法的代码: SM2:国密算法 SM2 公钥加密 非对称加密 数字签名 密钥协商 python实现完 ...
- 基于国密算法实现主机之间的密钥分发和安全传输-2021西北工业大学网络空间安全学院暑期夏令营
2021年西北工业大学网络空间安全学院暑期夏令营 一.设计内容与要求: 二.基本思路与实现: 三.设计原理与流程: 3.1 总体流程: 3.2 设计原理: 3.2.1 建立套接字连接: 3.2.2 根 ...
- 国密算法分类总结:sm2,sm3,sm4等
前面几篇博文对sm2,sm3,sm4,rsa,des等算法进行了介绍,并且用java,python语言实现了相关算法的运用. 本篇,作为一个阶段性总结,从整体上来回顾一下密码相关业务.当然,重点还是要 ...
- 爬虫逆向基础,认识 SM1/SM2/SM3/SM4/SM7/SM9/ZUC 国密算法
文章目录 [01x00] 简介 [02x00]算法概述 [03x00]算法详解 [03x01]SM1 分组加密算法 [03x02]SM2 椭圆曲线公钥加密算法 [03x03]SM3 杂凑算法 [03x ...
- java sm_Java国密SM2/SM3/SM4及证书
1. 使用BC库1.59版本已经可以支持国密算法SM2/SM3/SM4,某大神写的详细测试例子:https://github.com/ZZMarquis/gmhelper 2. 制作证书参考网上资料简 ...
最新文章
- python类直接调用不实例化_未实例化类的python调用方法
- Prefactoring——Guidelines
- 高数第七章知识点框架
- 分组中查询不符合条件的组
- jsp中为什么在跳转500页面的时候 图片加载不出来
- mysql实现内容加密_简单为mysql 实现透明加密方法
- 手把手教你感情企划书
- Centos7+ 修改hostname主机名命令
- 【洛谷P1314】聪明的质检员(二分+前缀和+差分)
- 日报系统、周报系统如何便捷使用?——领导篇
- webm格式转换mp4_将webm转换为mp4
- python画三色柱状图_python画柱状图--不同颜色并显示数值的方法
- windows7副本不是正版问题
- 遇到的一个网页排版问题
- 设置TextView滚动
- [bzoj4698][SDOI2008]Sandy的卡片
- 第一周学习前端html的知识总结与感悟
- keil MDK AC6设置noinit的用法
- 赛宁网安合作伙伴大会成功举办,重磅发布SCBaaS服务!
- Android-app内部调整字体大小