前言
对于很多企业来说,都在进行国密改造,要求使用国密代替传统的国际算法,国密算法分为 SM1、SM2、SM3、SM4,比较常见是的 2-4:
-
对称加密算法:
-
SM4:SM4算法是一种128位分组加密算法,密钥长度也为128位,适用于大量数据的快速加密。
-
非对称加密算法:
-
SM2:SM2算法基于椭圆曲线密码学,用于实现公钥加密和数字签名。它包括密钥生成、加密、解密和数字签名等功能。
-
哈希算法:
-
SM3:SM3是一种密码哈希函数,用于生成消息摘要,可用于数据完整性校验、消息认证码(MAC)生成等用途。
-
数字签名算法:
-
SM2算法也用于数字签名,通过私钥对消息摘要进行签名,公钥用于验证签名的真实性。
通过 JAVA 代码分别实现
常见 maven 仓库,在 pom 中加载 BC 包:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.72</version>
</dependency>
对 SM2-4 实现的代码如下,供大家参考
1. package com.example.bc;
3. import java.security.KeyPair;
4. import java.security.KeyPairGenerator;
5. import java.security.SecureRandom;
6. import java.security.Security;
8. import javax.crypto.Cipher;
9. import javax.crypto.spec.SecretKeySpec;
10. import javax.crypto.spec.IvParameterSpec;
12. import org.bouncycastle.asn1.bc.SignatureCheck;
13. import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
14. import org.bouncycastle.asn1.ocsp.Signature;
15. import org.bouncycastle.crypto.CipherParameters;
16. import org.bouncycastle.crypto.digests.SM3Digest;
17. import org.bouncycastle.crypto.macs.HMac;
18. import org.bouncycastle.crypto.params.KeyParameter;
19. import org.bouncycastle.crypto.params.ParametersWithRandom;
20. import org.bouncycastle.crypto.signers.SM2Signer;
21. import org.bouncycastle.jce.provider.BouncyCastleProvider;
22. import org.bouncycastle.util.encoders.Hex;
24. /**
25. * Hello world!
26. *
27. */
28. public class App
29. {
30. public static void main( String[] args ) throws Exception
31. {
32. //加载 bc provider
33. Security.addProvider(new BouncyCastleProvider());
34. String plainText = "HelloWord!";
35. byte[] messagebytes = plainText.getBytes();
36. SecureRandom secureRandom = new SecureRandom();
38. // 生成密钥
39. System.out.println("Demo1: sm2 加解密:n");
40. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
41. keyPairGenerator.initialize(256, secureRandom);
42. KeyPair keyPair = keyPairGenerator.generateKeyPair();
43. System.out.println("公钥:" + Hex.toHexString(keyPair.getPublic().getEncoded()));
44. System.out.println("私钥:" + Hex.toHexString(keyPair.getPrivate().getEncoded()));
45. //加密
47. Cipher cipher = Cipher.getInstance("SM2","BC");
48. cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
49. byte[] encryptedbytes = cipher.doFinal(messagebytes);
50. System.out.println("加密后:" + Hex.toHexString(encryptedbytes));
51. //解密
52. Cipher cipher1 = Cipher.getInstance("SM2","BC");
53. cipher1.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
54. byte[] decryptedbytes = cipher1.doFinal(encryptedbytes);
55. System.out.println("解密后:" + new String(decryptedbytes));
57. System.out.println("---------------------------------------------------------");
58. System.out.println("Demo2: sm3 哈希:n");
59. SM3Digest sm3 = new SM3Digest();
60. sm3.update(messagebytes,0,messagebytes.length);
61. byte[] result = new byte[sm3.getDigestSize()];
62. sm3.doFinal(result, 0);
63. System.out.println("哈希后:" + Hex.toHexString(result));
65. System.out.println("---------------------------------------------------------");
66. System.out.println("Demo3: sm4 加解密:n");
67. //生成随机数作为密钥和 IV 值
68. byte[] key = new byte[16];
69. secureRandom.nextBytes(key);
70. byte[] iv = new byte[16];
71. secureRandom.nextBytes(iv);
72. // IvAlgorithmParameters ivSpec = new IvAlgorithmParameters();
73. IvParameterSpec ivSpec = new IvParameterSpec(iv);
75. System.out.println("密钥:" + Hex.toHexString(key));
76. System.out.println("向量:" + Hex.toHexString(iv));
78. Cipher cipher2 = Cipher.getInstance("SM4/CBC/PKCS5Padding","BC");
79. cipher2.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "SM4"), ivSpec);
80. byte[] encryptedbytes2 = cipher2.doFinal(messagebytes);
81. System.out.println("加密后:" + Hex.toHexString(encryptedbytes2));
82. cipher2.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "SM4"), ivSpec);
83. byte[] decryptedbytes2 = cipher2.doFinal(encryptedbytes2);
84. System.out.println("解密后:" + new String(decryptedbytes2));
86. //Hmac算法
87. System.out.println("---------------------------------------------------------");
88. System.out.println("Demo4: sm4 hmac:n");
89. byte[] key2 = new byte[16];
90. secureRandom.nextBytes(key2);
91. System.out.println("密钥:" + Hex.toHexString(key2));
93. HMac hMac = new HMac(new SM3Digest());
94. hMac.init(new KeyParameter(key));
95. hMac.update(messagebytes,0,messagebytes.length);
96. byte[] result2 = new byte[hMac.getMacSize()];
97. hMac.doFinal(result2, 0);
98. System.out.println("hmac后:" + Hex.toHexString(result2));
100. }
102. }
其他可使用的包
腾讯Kona国密套件(如KonaCrypto),该套件已在GitHub上开源:https://github.com/Tencent/TencentKonaSMSuite,相对于 BC 来说可能更好用一些,BC 貌似对签名验签并不支持,在使用 BC 包的时候没能实现签名验签的代码。
原文始发于微信公众号(YY的黑板报):基于 BC 包实现国密
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论