SM Java实现

本文提供了一篇关于国密算法SM2和SM3在Java中的实现方法,包括源码下载链接和项目目录结构。文章强调了在网络中找到的Java实现并不多,且跨语言加密解密可能存在问题。需要依赖bcprov-jdk.jar库,并给出了各个关键类的概述。
摘要由CSDN通过智能技术生成

推荐一个大神的人工智能教程!http://blog.csdn.net/jiangjunshow

【摘要】

本文主要讲解“国密加密算法”SM系列的Java实现方法,不涉及具体的算法剖析,在网络上找到的java实现方法比较少,切在跨语言加密解密上会存在一些问题,所以整理此文志之。

源码下载地址http://download.csdn.net/detail/ererfei/9474502 需要C#实现SM系列算法源码的可以评论留邮箱地址,看到后发送

1.SM2 & SM3

由于SM2算法中需要使用SM3摘要算法,所以把他们放在一起

项目目录结构如下:


首先要下载一个jar包——bcprov-jdk.jar,可以到maven库中下载最新版http://central.maven.org/maven2/org/bouncycastle/并将该jar包引入项目的classpath。实现代码如下(每个工具类都有Main可以运行测试):

a.      SM2主类

【SM2.java】

 


 
 
 
  1. package com.mlq.sm;
  2. import java.math.BigInteger;
  3. import java.security.SecureRandom;
  4. import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
  5. import org.bouncycastle.crypto.params.ECDomainParameters;
  6. import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
  7. import org.bouncycastle.math.ec.ECCurve;
  8. import org.bouncycastle.math.ec.ECFieldElement;
  9. import org.bouncycastle.math.ec.ECPoint;
  10. import org.bouncycastle.math.ec.ECFieldElement.Fp;
  11. public class SM2
  12. {
  13. //测试参数
  14. // public static final String[] ecc_param = {
  15. // "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3",
  16. // "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498",
  17. // "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A",
  18. // "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7",
  19. // "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D",
  20. // "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"
  21. // };
  22. //正式参数
  23. public static String[] ecc_param = {
  24. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
  25. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
  26. "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
  27. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
  28. "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
  29. "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
  30. };
  31. public static SM2 Instance()
  32. {
  33. return new SM2();
  34. }
  35. public final BigInteger ecc_p;
  36. public final BigInteger ecc_a;
  37. public final BigInteger ecc_b;
  38. public final BigInteger ecc_n;
  39. public final BigInteger ecc_gx;
  40. public final BigInteger ecc_gy;
  41. public final ECCurve ecc_curve;
  42. public final ECPoint ecc_point_g;
  43. public final ECDomainParameters ecc_bc_spec;
  44. public final ECKeyPairGenerator ecc_key_pair_generator;
  45. public final ECFieldElement ecc_gx_fieldelement;
  46. public final ECFieldElement ecc_gy_fieldelement;
  47. public SM2()
  48. {
  49. this.ecc_p = new BigInteger(ecc_param[ 0], 16);
  50. this.ecc_a = new BigInteger(ecc_param[ 1], 16);
  51. this.ecc_b = new BigInteger(ecc_param[ 2], 16);
  52. this.ecc_n = new BigInteger(ecc_param[ 3], 16);
  53. this.ecc_gx = new BigInteger(ecc_param[ 4], 16);
  54. this.ecc_gy = new BigInteger(ecc_param[ 5], 16);
  55. this.ecc_gx_fieldelement = new Fp( this.ecc_p, this.ecc_gx);
  56. this.ecc_gy_fieldelement = new Fp( this.ecc_p, this.ecc_gy);
  57. this.ecc_curve = new ECCurve.Fp( this.ecc_p, this.ecc_a, this.ecc_b);
  58. this.ecc_point_g = new ECPoint.Fp( this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);
  59. this.ecc_bc_spec = new ECDomainParameters( this.ecc_curve, this.ecc_point_g, this.ecc_n);
  60. ECKeyGenerationParameters ecc_ecgenparam;
  61. ecc_ecgenparam = new ECKeyGenerationParameters( this.ecc_bc_spec, new SecureRandom());
  62. this.ecc_key_pair_generator = new ECKeyPairGenerator();
  63. this.ecc_key_pair_generator.init(ecc_ecgenparam);
  64. }
  65. }

b.      SM2工具类

【SM2Utils.java】

 


 
 
 
  1. package com.mlq.sm;
  2. import java.io.IOException;
  3. import java.math.BigInteger;
  4. import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
  5. import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
  6. import org.bouncycastle.crypto.params.ECPublicKeyParameters;
  7. import org.bouncycastle.math.ec.ECPoint;
  8. public class SM2Utils
  9. {
  10. //生成随机秘钥对
  11. public static void generateKeyPair(){
  12. SM2 sm2 = SM2.Instance();
  13. AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();
  14. ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
  15. ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
  16. BigInteger privateKey = ecpriv.getD();
  17. ECPoint publicKey = ecpub.getQ();
  18. System.out.println( "公钥: " + Util.byteToHex(publicKey.getEncoded()));
  19. System.out.println( "私钥: " + Util.byteToHex(privateKey.toByteArray()));
  20. }
  21. //数据加密
  22. public static String encrypt(byte[] publicKey, byte[] data) throws IOException
  23. {
  24. if (publicKey == null || publicKey.length == 0)
  25. {
  26. return null;
  27. }
  28. if (data == null || data.length == 0)
  29. {
  30. return null;
  31. }
  32. byte[] source = new byte[data.length];
  33. System.arraycopy(data, 0, source, 0, data.length);
  34. Cipher cipher = new Cipher();
  35. SM2 sm2 = SM2.Instance();
  36. ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
  37. ECPoint c1 = cipher.Init_enc(sm2, userKey);
  38. cipher.Encrypt(source);
  39. byte[] c3 = new byte[ 32];
  40. cipher.Dofinal(c3);
  41. // System.out.println("C1 " + Util.byteToHex(c1.getEncoded()));
  42. // System.out.println("C2 " + Util.byteToHex(source));
  43. // System.out.println("C3 " + Util.byteToHex(c3));
  44. //C1 C2 C3拼装成加密字串
  45. return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(source) + Util.byteToHex(c3);
  46. }
  47. //数据解密
  48. public static byte[] decrypt( byte[] privateKey, byte[] encryptedData) throws IOException
  49. {
  50. if (privateKey == null || privateKey.length == 0)
  51. {
  52. return null;
  53. }
  54. if (encryptedData == null || encryptedData.length == 0)
  55. {
  56. return null;
  57. }
  58. //加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2
  59. String data = Util.byteToHex(encryptedData);
  60. /***分解加密字串
  61. * (C1 = C1标志位2位 + C1实体部分128位 = 130)
  62. * (C3 = C3实体部分64位 = 64)
  63. * (C2 = encryptedData.length * 2 - C1长度 - C2长度)
  64. */
  65. byte[] c1Bytes = Util.hexToByte(data.substring( 0, 130));
  66. int c2Len = encryptedData.length - 97;
  67. byte[] c2 = Util.hexToByte(data.substring( 130, 130 + 2 * c2Len));
  68. byte[] c3 = Util.hexToByte(data.substring( 130 + 2 * c2Len, 194 + 2 * c2Len));
  69. SM2 sm2 = SM2.Instance();
  70. BigInteger userD = new BigInteger( 1, privateKey);
  71. //通过C1实体字节来生成ECPoint
  72. ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
  73. Cipher cipher = new Cipher();
  74. cipher.Init_dec(userD, c1);
  75. cipher.Decrypt(c2);
  76. cipher.Dofinal(c3);
  77. //返回解密结果
  78. return c2;
  79. }
  80. public static void main(String[] args) throws Exception
  81. {
  82. //生成密钥对
  83. generateKeyPair();
  84. String plainText = "ererfeiisgod";
  85. byte[] sourceData = plainText.getBytes();
  86. //下面的秘钥可以使用generateKeyPair()生成的秘钥内容
  87. // 国密规范正式私钥
  88. String prik = "3690655E33D5EA3D9A4AE1A1ADD766FDEA045CDEAA43A9206FB8C430CEFE0D94";
  89. // 国密规范正式公钥
  90. String pubk = "04F6E0C3345AE42B51E06BF50B98834988D54EBC7460FE135A48171BC0629EAE205EEDE253A530608178A98F1E19BB737302813BA39ED3FA3C51639D7A20C7391A";
  91. System.out.println( "加密: ");
  92. String cipherText = SM2Utils.encrypt(Util.hexToByte(pubk), sourceData);
  93. System.out.println(cipherText);
  94. System.out.println( "解密: ");
  95. plainText = new String(SM2Utils.decrypt(Util.hexToByte(prik), Util.hexToByte(cipherText)));
  96. System.out.println(plainText);
  97. }
  98. }

c.      SM3主类

【SM3.java】

 


 
 
 
  1. package com.mlq.sm;
  2. public class SM3
  3. {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值