Java实现国密算法SM2,SM3,SM4,并且实现ECB和CBC模式

代码中实现了电码本ECB模式和密文分组连接CBC模式,SM3.java和SM4.java为算法实现类,utils的都是根据实现类写的工具,可以根据需要调用杂凑算法SM3的杂凑功能获得杂凑值。

图片[1]-Java实现国密算法SM2,SM3,SM4,并且实现ECB和CBC模式-第五维

图片[2]-Java实现国密算法SM2,SM3,SM4,并且实现ECB和CBC模式-第五维

SM4.java中

sm4_crypt_ecb(SM4_Context ctx, byte[] input)      ECB模式加解密方法,根据密钥判断加解密功能

sm4_crypt_cbc(SM4_Context ctx, byte[] iv, byte[] input)      CBC模式加解密方法,根据密钥判断加解密功能

加密解密通过如下方法:

sm4_setkey_enc(SM4_Context ctx, byte[] key)  设置加密密钥调用上述方法,实现加密

sm4_setkey_dec(SM4_Context ctx, byte[] key)  设置解密密钥调用上述方法,实现解密

需要导入的包为bcprov-jdk16  我用的版本是bcprov-jdk16-1.46

maven中配置依赖:

  1. <dependency>
  2. <groupId>org.bouncycastle</groupId>
  3. <artifactId></artifactId>
  4. <version>1.46</version>
  5. </dependency>

 

package中class目录如下:

图片[3]-Java实现国密算法SM2,SM3,SM4,并且实现ECB和CBC模式-第五维

chiper.java

  1. import java.math.BigInteger;
  2. import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
  3. import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
  4. import org.bouncycastle.crypto.params.ECPublicKeyParameters;
  5. import org.bouncycastle.math.ec.ECPoint;
  6. public class Cipher {
  7. private int ct;
  8. private ECPoint p2;
  9. private SM3Digest sm3keybase;
  10. private SM3Digest sm3c3;
  11. private byte key[];
  12. private byte keyOff;
  13. public Cipher()
  14. {
  15. this.ct = 1;
  16. this.key = new byte[32];
  17. this.keyOff = 0;
  18. }
  19. private void Reset()
  20. {
  21. this.sm3keybase = new SM3Digest();
  22. this.sm3c3 = new SM3Digest();
  23. byte p[] = Util.byteConvert32Bytes(p2.getX().toBigInteger());
  24. this.sm3keybase.update(p, 0, p.length);
  25. this.sm3c3.update(p, 0, p.length);
  26. p = Util.byteConvert32Bytes(p2.getY().toBigInteger());
  27. this.sm3keybase.update(p, 0, p.length);
  28. this.ct = 1;
  29. NextKey();
  30. }
  31. private void NextKey()
  32. {
  33. SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);
  34. sm3keycur.update((byte) (ct >> 24 & 0xff));
  35. sm3keycur.update((byte) (ct >> 16 & 0xff));
  36. sm3keycur.update((byte) (ct >> 8 & 0xff));
  37. sm3keycur.update((byte) (ct & 0xff));
  38. sm3keycur.doFinal(key, 0);
  39. this.keyOff = 0;
  40. this.ct++;
  41. }
  42. public ECPoint Init_enc(SM2 sm2, ECPoint userKey)
  43. {
  44. AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();
  45. ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
  46. ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
  47. BigInteger k = ecpriv.getD();
  48. ECPoint c1 = ecpub.getQ();
  49. this.p2 = userKey.multiply(k);
  50. Reset();
  51. return c1;
  52. }
  53. public void Encrypt(byte data[])
  54. {
  55. this.sm3c3.update(data, 0, data.length);
  56. for (int i = 0; i < data.length; i++)
  57. {
  58. if (keyOff == key.length)
  59. {
  60. NextKey();
  61. }
  62. data[i] ^= key[keyOff++];
  63. }
  64. }
  65. public void Init_dec(BigInteger userD, ECPoint c1)
  66. {
  67. this.p2 = c1.multiply(userD);
  68. Reset();
  69. }
  70. public void Decrypt(byte data[])
  71. {
  72. for (int i = 0; i < data.length; i++)
  73. {
  74. if (keyOff == key.length)
  75. {
  76. NextKey();
  77. }
  78. data[i] ^= key[keyOff++];
  79. }
  80. this.sm3c3.update(data, 0, data.length);
  81. }
  82. public void Dofinal(byte c3[])
  83. {
  84. byte p[] = Util.byteConvert32Bytes(p2.getY().toBigInteger());
  85. this.sm3c3.update(p, 0, p.length);
  86. this.sm3c3.doFinal(c3, 0);
  87. Reset();
  88. }
  89. }

SM2.java

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

SM2Utils.java

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

SM3.java

  1. public class SM3 {
  2. public static final byte[] iv = { 0x73, (byte) 0x80, 0x16, 0x6f, 0x49,
  3. 0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte) 0xd7,
  4. (byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30,
  5. (byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte) 0xe3,
  6. (byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb, 0x0e,
  7. 0x4e };
  8. public static int[] Tj = new int[64];
  9. static
  10. {
  11. for (int i = 0; i < 16; i++)
  12. {
  13. Tj[i] = 0x79cc4519;
  14. }
  15. for (int i = 16; i < 64; i++)
  16. {
  17. Tj[i] = 0x7a879d8a;
  18. }
  19. }
  20. public static byte[] CF(byte[] V, byte[] B)
  21. {
  22. int[] v, b;
  23. v = convert(V);
  24. b = convert(B);
  25. return convert(CF(v, b));
  26. }
  27. private static int[] convert(byte[] arr)
  28. {
  29. int[] out = new int[arr.length / 4];
  30. byte[] tmp = new byte[4];
  31. for (int i = 0; i < arr.length; i += 4)
  32. {
  33. System.arraycopy(arr, i, tmp, 0, 4);
  34. out[i / 4] = bigEndianByteToInt(tmp);
  35. }
  36. return out;
  37. }
  38. private static byte[] convert(int[] arr)
  39. {
  40. byte[] out = new byte[arr.length * 4];
  41. byte[] tmp = null;
  42. for (int i = 0; i < arr.length; i++)
  43. {
  44. tmp = bigEndianIntToByte(arr[i]);
  45. System.arraycopy(tmp, 0, out, i * 4, 4);
  46. }
  47. return out;
  48. }
  49. public static int[] CF(int[] V, int[] B)
  50. {
  51. int a, b, c, d, e, f, g, h;
  52. int ss1, ss2, tt1, tt2;
  53. a = V[0];
  54. b = V[1];
  55. c = V[2];
  56. d = V[3];
  57. e = V[4];
  58. f = V[5];
  59. g = V[6];
  60. h = V[7];
  61. int[][] arr = expand(B);
  62. int[] w = arr[0];
  63. int[] w1 = arr[1];
  64. for (int j = 0; j < 64; j++)
  65. {
  66. ss1 = (bitCycleLeft(a, 12) + e + bitCycleLeft(Tj[j], j));
  67. ss1 = bitCycleLeft(ss1, 7);
  68. ss2 = ss1 ^ bitCycleLeft(a, 12);
  69. tt1 = FFj(a, b, c, j) + d + ss2 + w1[j];
  70. tt2 = GGj(e, f, g, j) + h + ss1 + w[j];
  71. d = c;
  72. c = bitCycleLeft(b, 9);
  73. b = a;
  74. a = tt1;
  75. h = g;
  76. g = bitCycleLeft(f, 19);
  77. f = e;
  78. e = P0(tt2);
  79. /*System.out.print(j+” “);
  80. System.out.print(Integer.toHexString(a)+” “);
  81. System.out.print(Integer.toHexString(b)+” “);
  82. System.out.print(Integer.toHexString(c)+” “);
  83. System.out.print(Integer.toHexString(d)+” “);
  84. System.out.print(Integer.toHexString(e)+” “);
  85. System.out.print(Integer.toHexString(f)+” “);
  86. System.out.print(Integer.toHexString(g)+” “);
  87. System.out.print(Integer.toHexString(h)+” “);
  88. System.out.println(“”);*/
  89. }
  90. // System.out.println(“”);
  91. int[] out = new int[8];
  92. out[0] = a ^ V[0];
  93. out[1] = b ^ V[1];
  94. out[2] = c ^ V[2];
  95. out[3] = d ^ V[3];
  96. out[4] = e ^ V[4];
  97. out[5] = f ^ V[5];
  98. out[6] = g ^ V[6];
  99. out[7] = h ^ V[7];
  100. return out;
  101. }
  102. private static int[][] expand(int[] B)
  103. {
  104. int W[] = new int[68];
  105. int W1[] = new int[64];
  106. for (int i = 0; i < B.length; i++)
  107. {
  108. W[i] = B[i];
  109. }
  110. for (int i = 16; i < 68; i++)
  111. {
  112. W[i] = P1(W[i – 16] ^ W[i – 9] ^ bitCycleLeft(W[i – 3], 15))
  113. ^ bitCycleLeft(W[i – 13], 7) ^ W[i – 6];
  114. }
  115. for (int i = 0; i < 64; i++)
  116. {
  117. W1[i] = W[i] ^ W[i + 4];
  118. }
  119. int arr[][] = new int[][] { W, W1 };
  120. return arr;
  121. }
  122. private static byte[] bigEndianIntToByte(int num)
  123. {
  124. return back(Util.intToBytes(num));
  125. }
  126. private static int bigEndianByteToInt(byte[] bytes)
  127. {
  128. return Util.byteToInt(back(bytes));
  129. }
  130. private static int FFj(int X, int Y, int Z, int j)
  131. {
  132. if (j >= 0 && j <= 15)
  133. {
  134. return FF1j(X, Y, Z);
  135. }
  136. else
  137. {
  138. return FF2j(X, Y, Z);
  139. }
  140. }
  141. private static int GGj(int X, int Y, int Z, int j)
  142. {
  143. if (j >= 0 && j <= 15)
  144. {
  145. return GG1j(X, Y, Z);
  146. }
  147. else
  148. {
  149. return GG2j(X, Y, Z);
  150. }
  151. }
  152. // 逻辑位运算函数
  153. private static int FF1j(int X, int Y, int Z)
  154. {
  155. int tmp = X ^ Y ^ Z;
  156. return tmp;
  157. }
  158. private static int FF2j(int X, int Y, int Z)
  159. {
  160. int tmp = ((X & Y) | (X & Z) | (Y & Z));
  161. return tmp;
  162. }
  163. private static int GG1j(int X, int Y, int Z)
  164. {
  165. int tmp = X ^ Y ^ Z;
  166. return tmp;
  167. }
  168. private static int GG2j(int X, int Y, int Z)
  169. {
  170. int tmp = (X & Y) | (~X & Z);
  171. return tmp;
  172. }
  173. private static int P0(int X)
  174. {
  175. int y = rotateLeft(X, 9);
  176. y = bitCycleLeft(X, 9);
  177. int z = rotateLeft(X, 17);
  178. z = bitCycleLeft(X, 17);
  179. int t = X ^ y ^ z;
  180. return t;
  181. }
  182. private static int P1(int X)
  183. {
  184. int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23);
  185. return t;
  186. }
  187. /**
  188. * 对最后一个分组字节数据padding
  189. *
  190. * @param in
  191. * @param bLen
  192. * 分组个数
  193. * @return
  194. */
  195. public static byte[] padding(byte[] in, int bLen)
  196. {
  197. int k = 448 – (8 * in.length + 1) % 512;
  198. if (k < 0)
  199. {
  200. k = 960 – (8 * in.length + 1) % 512;
  201. }
  202. k += 1;
  203. byte[] padd = new byte[k / 8];
  204. padd[0] = (byte) 0x80;
  205. long n = in.length * 8 + bLen * 512;
  206. byte[] out = new byte[in.length + k / 8 + 64 / 8];
  207. int pos = 0;
  208. System.arraycopy(in, 0, out, 0, in.length);
  209. pos += in.length;
  210. System.arraycopy(padd, 0, out, pos, padd.length);
  211. pos += padd.length;
  212. byte[] tmp = back(Util.longToBytes(n));
  213. System.arraycopy(tmp, 0, out, pos, tmp.length);
  214. return out;
  215. }
  216. /**
  217. * 字节数组逆序
  218. *
  219. * @param in
  220. * @return
  221. */
  222. private static byte[] back(byte[] in)
  223. {
  224. byte[] out = new byte[in.length];
  225. for (int i = 0; i < out.length; i++)
  226. {
  227. out[i] = in[out.length – i – 1];
  228. }
  229. return out;
  230. }
  231. public static int rotateLeft(int x, int n)
  232. {
  233. return (x << n) | (x >> (32 – n));
  234. }
  235. private static int bitCycleLeft(int n, int bitLen)
  236. {
  237. bitLen %= 32;
  238. byte[] tmp = bigEndianIntToByte(n);
  239. int byteLen = bitLen / 8;
  240. int len = bitLen % 8;
  241. if (byteLen > 0)
  242. {
  243. tmp = byteCycleLeft(tmp, byteLen);
  244. }
  245. if (len > 0)
  246. {
  247. tmp = bitSmall8CycleLeft(tmp, len);
  248. }
  249. return bigEndianByteToInt(tmp);
  250. }
  251. private static byte[] bitSmall8CycleLeft(byte[] in, int len)
  252. {
  253. byte[] tmp = new byte[in.length];
  254. int t1, t2, t3;
  255. for (int i = 0; i < tmp.length; i++)
  256. {
  257. t1 = (byte) ((in[i] & 0x000000ff) << len);
  258. t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 – len));
  259. t3 = (byte) (t1 | t2);
  260. tmp[i] = (byte) t3;
  261. }
  262. return tmp;
  263. }
  264. private static byte[] byteCycleLeft(byte[] in, int byteLen)
  265. {
  266. byte[] tmp = new byte[in.length];
  267. System.arraycopy(in, byteLen, tmp, 0, in.length – byteLen);
  268. System.arraycopy(in, 0, tmp, in.length – byteLen, byteLen);
  269. return tmp;
  270. }
  271. }

SM3Digest.java

  1. import org.bouncycastle.util.encoders.Hex;
  2. public class SM3Digest {
  3. /** SM3值的长度 */
  4. private static final int BYTE_LENGTH = 32;
  5. /** SM3分组长度 */
  6. private static final int BLOCK_LENGTH = 64;
  7. /** 缓冲区长度 */
  8. private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1;
  9. /** 缓冲区 */
  10. private byte[] xBuf = new byte[BUFFER_LENGTH];
  11. /** 缓冲区偏移量 */
  12. private int xBufOff;
  13. /** 初始向量 */
  14. private byte[] V = SM3.iv.clone();
  15. private int cntBlock = 0;
  16. public SM3Digest() {
  17. }
  18. public SM3Digest(SM3Digest t)
  19. {
  20. System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
  21. this.xBufOff = t.xBufOff;
  22. System.arraycopy(t.V, 0, this.V, 0, t.V.length);
  23. }
  24. /**
  25. * SM3结果输出
  26. *
  27. * @param out 保存SM3结构的缓冲区
  28. * @param outOff 缓冲区偏移量
  29. * @return
  30. */
  31. public int doFinal(byte[] out, int outOff)
  32. {
  33. byte[] tmp = doFinal();
  34. System.arraycopy(tmp, 0, out, 0, tmp.length);
  35. return BYTE_LENGTH;
  36. }
  37. public void reset()
  38. {
  39. xBufOff = 0;
  40. cntBlock = 0;
  41. V = SM3.iv.clone();
  42. }
  43. /**
  44. * 明文输入
  45. *
  46. * @param in
  47. * 明文输入缓冲区
  48. * @param inOff
  49. * 缓冲区偏移量
  50. * @param len
  51. * 明文长度
  52. */
  53. public void update(byte[] in, int inOff, int len)
  54. {
  55. int partLen = BUFFER_LENGTH – xBufOff;
  56. int inputLen = len;
  57. int dPos = inOff;
  58. if (partLen < inputLen)
  59. {
  60. System.arraycopy(in, dPos, xBuf, xBufOff, partLen);
  61. inputLen -= partLen;
  62. dPos += partLen;
  63. doUpdate();
  64. while (inputLen > BUFFER_LENGTH)
  65. {
  66. System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH);
  67. inputLen -= BUFFER_LENGTH;
  68. dPos += BUFFER_LENGTH;
  69. doUpdate();
  70. }
  71. }
  72. System.arraycopy(in, dPos, xBuf, xBufOff, inputLen);
  73. xBufOff += inputLen;
  74. }
  75. private void doUpdate()
  76. {
  77. byte[] B = new byte[BLOCK_LENGTH];
  78. for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH)
  79. {
  80. System.arraycopy(xBuf, i, B, 0, B.length);
  81. doHash(B);
  82. }
  83. xBufOff = 0;
  84. }
  85. private void doHash(byte[] B)
  86. {
  87. byte[] tmp = SM3.CF(V, B);
  88. System.arraycopy(tmp, 0, V, 0, V.length);
  89. cntBlock++;
  90. }
  91. private byte[] doFinal()
  92. {
  93. byte[] B = new byte[BLOCK_LENGTH];
  94. byte[] buffer = new byte[xBufOff];
  95. System.arraycopy(xBuf, 0, buffer, 0, buffer.length);
  96. byte[] tmp = SM3.padding(buffer, cntBlock);
  97. for (int i = 0; i < tmp.length; i += BLOCK_LENGTH)
  98. {
  99. System.arraycopy(tmp, i, B, 0, B.length);
  100. doHash(B);
  101. }
  102. return V;
  103. }
  104. public void update(byte in)
  105. {
  106. byte[] buffer = new byte[] { in };
  107. update(buffer, 0, 1);
  108. }
  109. public int getDigestSize()
  110. {
  111. return BYTE_LENGTH;
  112. }
  113. public static void main(String[] args)
  114. {
  115. byte[] md = new byte[32];
  116. byte[] msg1 = “ererfeiisgod”.getBytes();
  117. SM3Digest sm3 = new SM3Digest();
  118. sm3.update(msg1, 0, msg1.length);
  119. sm3.doFinal(md, 0);
  120. String s = new String(Hex.encode(md));
  121. System.out.println(s.toUpperCase());
  122. }
  123. }

SM4_Context.java

  1. public class SM4_Context {
  2. public int mode;
  3. public long[] sk;
  4. public boolean isPadding;
  5. public SM4_Context()
  6. {
  7. this.mode = 1;
  8. this.isPadding = true;
  9. this.sk = new long[32];
  10. }
  11. }

SM4.java

  1. import java.io.ByteArrayInputStream;
  2. import java.io.ByteArrayOutputStream;
  3. public class SM4 {
  4. public static final int SM4_ENCRYPT = 1;
  5. public static final int SM4_DECRYPT = 0;
  6. private long GET_ULONG_BE(byte[] b, int i)
  7. {
  8. long n = (long)(b[i] & 0xff) << 24 | (long)((b[i + 1] & 0xff) << 16) | (long)((b[i + 2] & 0xff) << 8) | (long)(b[i + 3] & 0xff) & 0xffffffffL;
  9. return n;
  10. }
  11. private void PUT_ULONG_BE(long n, byte[] b, int i)
  12. {
  13. b[i] = (byte)(int)(0xFF & n >> 24);
  14. b[i + 1] = (byte)(int)(0xFF & n >> 16);
  15. b[i + 2] = (byte)(int)(0xFF & n >> 8);
  16. b[i + 3] = (byte)(int)(0xFF & n);
  17. }
  18. private long SHL(long x, int n)
  19. {
  20. return (x & 0xFFFFFFFF) << n;
  21. }
  22. private long ROTL(long x, int n)
  23. {
  24. return SHL(x, n) | x >> (32 – n);
  25. }
  26. private void SWAP(long[] sk, int i)
  27. {
  28. long t = sk[i];
  29. sk[i] = sk[(31 – i)];
  30. sk[(31 – i)] = t;
  31. }
  32. public static final byte[] SboxTable = { (byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe,
  33. (byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6,
  34. 0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
  35. (byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,
  36. (byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,
  37. (byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91,
  38. (byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
  39. (byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
  40. (byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8,
  41. (byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa,
  42. 0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7,
  43. (byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83,
  44. 0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8,
  45. 0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda,
  46. (byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
  47. (byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
  48. (byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87,
  49. (byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27,
  50. 0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4,
  51. (byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a,
  52. (byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3,
  53. (byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15,
  54. (byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,
  55. (byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32,
  56. 0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d,
  57. (byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca,
  58. 0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
  59. (byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,
  60. (byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
  61. 0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb,
  62. (byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41,
  63. 0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,
  64. (byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d,
  65. 0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4,
  66. (byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,
  67. (byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09,
  68. (byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0,
  69. 0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,
  70. (byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48 };
  71. public static final int[] FK = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
  72. public static final int[] CK = { 0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
  73. 0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
  74. 0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
  75. 0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
  76. 0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
  77. 0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
  78. 0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
  79. 0x10171e25,0x2c333a41,0x484f565d,0x646b7279 };
  80. private byte sm4Sbox(byte inch)
  81. {
  82. int i = inch & 0xFF;
  83. byte retVal = SboxTable[i];
  84. return retVal;
  85. }
  86. private long sm4Lt(long ka)
  87. {
  88. long bb = 0L;
  89. long c = 0L;
  90. byte[] a = new byte[4];
  91. byte[] b = new byte[4];
  92. PUT_ULONG_BE(ka, a, 0);
  93. b[0] = sm4Sbox(a[0]);
  94. b[1] = sm4Sbox(a[1]);
  95. b[2] = sm4Sbox(a[2]);
  96. b[3] = sm4Sbox(a[3]);
  97. bb = GET_ULONG_BE(b, 0);
  98. c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
  99. return c;
  100. }
  101. private long sm4F(long x0, long x1, long x2, long x3, long rk)
  102. {
  103. return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
  104. }
  105. private long sm4CalciRK(long ka)
  106. {
  107. long bb = 0L;
  108. long rk = 0L;
  109. byte[] a = new byte[4];
  110. byte[] b = new byte[4];
  111. PUT_ULONG_BE(ka, a, 0);
  112. b[0] = sm4Sbox(a[0]);
  113. b[1] = sm4Sbox(a[1]);
  114. b[2] = sm4Sbox(a[2]);
  115. b[3] = sm4Sbox(a[3]);
  116. bb = GET_ULONG_BE(b, 0);
  117. rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
  118. return rk;
  119. }
  120. private void sm4_setkey(long[] SK, byte[] key)
  121. {
  122. long[] MK = new long[4];
  123. long[] k = new long[36];
  124. int i = 0;
  125. MK[0] = GET_ULONG_BE(key, 0);
  126. MK[1] = GET_ULONG_BE(key, 4);
  127. MK[2] = GET_ULONG_BE(key, 8);
  128. MK[3] = GET_ULONG_BE(key, 12);
  129. k[0] = MK[0] ^ (long) FK[0];
  130. k[1] = MK[1] ^ (long) FK[1];
  131. k[2] = MK[2] ^ (long) FK[2];
  132. k[3] = MK[3] ^ (long) FK[3];
  133. for (; i < 32; i++)
  134. {
  135. k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long) CK[i]));
  136. SK[i] = k[(i + 4)];
  137. }
  138. }
  139. private void sm4_one_round(long[] sk, byte[] input, byte[] output)
  140. {
  141. int i = 0;
  142. long[] ulbuf = new long[36];
  143. ulbuf[0] = GET_ULONG_BE(input, 0);
  144. ulbuf[1] = GET_ULONG_BE(input, 4);
  145. ulbuf[2] = GET_ULONG_BE(input, 8);
  146. ulbuf[3] = GET_ULONG_BE(input, 12);
  147. while (i < 32)
  148. {
  149. ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
  150. i++;
  151. }
  152. PUT_ULONG_BE(ulbuf[35], output, 0);
  153. PUT_ULONG_BE(ulbuf[34], output, 4);
  154. PUT_ULONG_BE(ulbuf[33], output, 8);
  155. PUT_ULONG_BE(ulbuf[32], output, 12);
  156. }
  157. private byte[] padding(byte[] input, int mode)
  158. {
  159. if (input == null)
  160. {
  161. return null;
  162. }
  163. byte[] ret = (byte[]) null;
  164. if (mode == SM4_ENCRYPT)
  165. {
  166. int p = 16 – input.length % 16;
  167. ret = new byte[input.length + p];
  168. System.arraycopy(input, 0, ret, 0, input.length);
  169. for (int i = 0; i < p; i++)
  170. {
  171. ret[input.length + i] = (byte) p;
  172. }
  173. }
  174. else
  175. {
  176. int p = input[input.length – 1];
  177. ret = new byte[input.length – p];
  178. System.arraycopy(input, 0, ret, 0, input.length – p);
  179. }
  180. return ret;
  181. }
  182. public void sm4_setkey_enc(SM4_Context ctx, byte[] key) throws Exception
  183. {
  184. if (ctx == null)
  185. {
  186. throw new Exception(“ctx is null!”);
  187. }
  188. if (key == null || key.length != 16)
  189. {
  190. throw new Exception(“key error!”);
  191. }
  192. ctx.mode = SM4_ENCRYPT;
  193. sm4_setkey(ctx.sk, key);
  194. }
  195. public void sm4_setkey_dec(SM4_Context ctx, byte[] key) throws Exception
  196. {
  197. if (ctx == null)
  198. {
  199. throw new Exception(“ctx is null!”);
  200. }
  201. if (key == null || key.length != 16)
  202. {
  203. throw new Exception(“key error!”);
  204. }
  205. int i = 0;
  206. ctx.mode = SM4_DECRYPT;
  207. sm4_setkey(ctx.sk, key);
  208. for (i = 0; i < 16; i++)
  209. {
  210. SWAP(ctx.sk, i);
  211. }
  212. }
  213. public byte[] sm4_crypt_ecb(SM4_Context ctx, byte[] input) throws Exception
  214. {
  215. if (input == null)
  216. {
  217. throw new Exception(“input is null!”);
  218. }
  219. if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT))
  220. {
  221. input = padding(input, SM4_ENCRYPT);
  222. }
  223. int length = input.length;
  224. ByteArrayInputStream bins = new ByteArrayInputStream(input);
  225. ByteArrayOutputStream bous = new ByteArrayOutputStream();
  226. for(; length > 0; length -= 16)
  227. {
  228. byte[] in = new byte[16];
  229. byte[] out = new byte[16];
  230. bins.read(in);
  231. sm4_one_round(ctx.sk, in, out);
  232. bous.write(out);
  233. }
  234. byte[] output = bous.toByteArray();
  235. if (ctx.isPadding && ctx.mode == SM4_DECRYPT)
  236. {
  237. output = padding(output, SM4_DECRYPT);
  238. }
  239. bins.close();
  240. bous.close();
  241. return output;
  242. }
  243. public byte[] sm4_crypt_cbc(SM4_Context ctx, byte[] iv, byte[] input) throws Exception
  244. {
  245. if (iv == null || iv.length != 16)
  246. {
  247. throw new Exception(“iv error!”);
  248. }
  249. if (input == null)
  250. {
  251. throw new Exception(“input is null!”);
  252. }
  253. if (ctx.isPadding && ctx.mode == SM4_ENCRYPT)
  254. {
  255. input = padding(input, SM4_ENCRYPT);
  256. }
  257. int i = 0;
  258. int length = input.length;
  259. ByteArrayInputStream bins = new ByteArrayInputStream(input);
  260. ByteArrayOutputStream bous = new ByteArrayOutputStream();
  261. if (ctx.mode == SM4_ENCRYPT)
  262. {
  263. for(; length > 0; length -= 16)
  264. {
  265. byte[] in = new byte[16];
  266. byte[] out = new byte[16];
  267. byte[] out1 = new byte[16];
  268. bins.read(in);
  269. for (i = 0; i < 16; i++)
  270. {
  271. out[i] = ((byte) (in[i] ^ iv[i]));
  272. }
  273. sm4_one_round(ctx.sk, out, out1);
  274. System.arraycopy(out1, 0, iv, 0, 16);
  275. bous.write(out1);
  276. }
  277. }
  278. else
  279. {
  280. byte[] temp = new byte[16];
  281. for(; length > 0; length -= 16)
  282. {
  283. byte[] in = new byte[16];
  284. byte[] out = new byte[16];
  285. byte[] out1 = new byte[16];
  286. bins.read(in);
  287. System.arraycopy(in, 0, temp, 0, 16);
  288. sm4_one_round(ctx.sk, in, out);
  289. for (i = 0; i < 16; i++)
  290. {
  291. out1[i] = ((byte) (out[i] ^ iv[i]));
  292. }
  293. System.arraycopy(temp, 0, iv, 0, 16);
  294. bous.write(out1);
  295. }
  296. }
  297. byte[] output = bous.toByteArray();
  298. if (ctx.isPadding && ctx.mode == SM4_DECRYPT)
  299. {
  300. output = padding(output, SM4_DECRYPT);
  301. }
  302. bins.close();
  303. bous.close();
  304. return output;
  305. }
  306. }

SM4Utils.java

  1. import java.io.IOException;
  2. import java.util.regex.Matcher;
  3. import java.util.regex.Pattern;
  4. import sun.misc.BASE64Decoder;
  5. import sun.misc.BASE64Encoder;
  6. public class SM4Utils {
  7. // private String secretKey = “”;
  8. // private String iv = “”;
  9. // private boolean hexString = false;
  10. public String secretKey = “”;
  11. private String iv = “”;
  12. public boolean hexString = false;
  13. public SM4Utils()
  14. {
  15. }
  16. //
  17. // public byte encryptData_ECB1(byte[] inputStream){
  18. // try
  19. // {
  20. // SM4_Context ctx = new SM4_Context();
  21. // ctx.isPadding = true;
  22. // ctx.mode = SM4.SM4_ENCRYPT;
  23. //
  24. // byte[] keyBytes;
  25. // if (hexString)
  26. // {
  27. // keyBytes = Util.hexStringToBytes(secretKey);
  28. // }
  29. // else
  30. // {
  31. // keyBytes = secretKey.getBytes();
  32. // }
  33. //
  34. // SM4 sm4 = new SM4();
  35. // sm4.sm4_setkey_enc(ctx, keyBytes);
  36. // String cipherText = new BASE64Encoder().encode(inputStream);
  37. // if (cipherText != null && cipherText.trim().length() > 0)
  38. // {
  39. // Pattern p = Pattern.compile(“\\s*|\t|\r|\n”);
  40. // Matcher m = p.matcher(cipherText);
  41. // cipherText = m.replaceAll(“”);
  42. // }
  43. // return cipherText;
  44. // }
  45. // catch (Exception e)
  46. // {
  47. // e.printStackTrace();
  48. // return (Byte) null;
  49. // }
  50. // }
  51. public String encryptData_ECB(String plainText)
  52. {
  53. try
  54. {
  55. SM4_Context ctx = new SM4_Context();
  56. ctx.isPadding = true;
  57. ctx.mode = SM4.SM4_ENCRYPT;
  58. byte[] keyBytes;
  59. if (hexString)
  60. {
  61. keyBytes = Util.hexStringToBytes(secretKey);
  62. }
  63. else
  64. {
  65. keyBytes = secretKey.getBytes();
  66. }
  67. SM4 sm4 = new SM4();
  68. sm4.sm4_setkey_enc(ctx, keyBytes);
  69. byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainText.getBytes(“GBK”));
  70. String cipherText = new BASE64Encoder().encode(encrypted);
  71. if (cipherText != null && cipherText.trim().length() > 0)
  72. {
  73. Pattern p = Pattern.compile(“\\s*|\t|\r|\n”);
  74. Matcher m = p.matcher(cipherText);
  75. cipherText = m.replaceAll(“”);
  76. }
  77. return cipherText;
  78. }
  79. catch (Exception e)
  80. {
  81. e.printStackTrace();
  82. return null;
  83. }
  84. }
  85. public String decryptData_ECB(String cipherText)
  86. {
  87. try
  88. {
  89. SM4_Context ctx = new SM4_Context();
  90. ctx.isPadding = true;
  91. ctx.mode = SM4.SM4_DECRYPT;
  92. byte[] keyBytes;
  93. if (hexString)
  94. {
  95. keyBytes = Util.hexStringToBytes(secretKey);
  96. }
  97. else
  98. {
  99. keyBytes = secretKey.getBytes();
  100. }
  101. SM4 sm4 = new SM4();
  102. sm4.sm4_setkey_dec(ctx, keyBytes);
  103. byte[] decrypted = sm4.sm4_crypt_ecb(ctx, new BASE64Decoder().decodeBuffer(cipherText));
  104. return new String(decrypted, “GBK”);
  105. }
  106. catch (Exception e)
  107. {
  108. e.printStackTrace();
  109. return null;
  110. }
  111. }
  112. public String encryptData_CBC(String plainText)
  113. {
  114. try
  115. {
  116. SM4_Context ctx = new SM4_Context();
  117. ctx.isPadding = true;
  118. ctx.mode = SM4.SM4_ENCRYPT;
  119. byte[] keyBytes;
  120. byte[] ivBytes;
  121. if (hexString)
  122. {
  123. keyBytes = Util.hexStringToBytes(secretKey);
  124. ivBytes = Util.hexStringToBytes(iv);
  125. }
  126. else
  127. {
  128. keyBytes = secretKey.getBytes();
  129. ivBytes = iv.getBytes();
  130. }
  131. SM4 sm4 = new SM4();
  132. sm4.sm4_setkey_enc(ctx, keyBytes);
  133. byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes(“GBK”));
  134. String cipherText = new BASE64Encoder().encode(encrypted);
  135. if (cipherText != null && cipherText.trim().length() > 0)
  136. {
  137. Pattern p = Pattern.compile(“\\s*|\t|\r|\n”);
  138. Matcher m = p.matcher(cipherText);
  139. cipherText = m.replaceAll(“”);
  140. }
  141. return cipherText;
  142. }
  143. catch (Exception e)
  144. {
  145. e.printStackTrace();
  146. return null;
  147. }
  148. }
  149. public String decryptData_CBC(String cipherText)
  150. {
  151. try
  152. {
  153. SM4_Context ctx = new SM4_Context();
  154. ctx.isPadding = true;
  155. ctx.mode = SM4.SM4_DECRYPT;
  156. byte[] keyBytes;
  157. byte[] ivBytes;
  158. if (hexString)
  159. {
  160. keyBytes = Util.hexStringToBytes(secretKey);
  161. ivBytes = Util.hexStringToBytes(iv);
  162. }
  163. else
  164. {
  165. keyBytes = secretKey.getBytes();
  166. ivBytes = iv.getBytes();
  167. }
  168. SM4 sm4 = new SM4();
  169. sm4.sm4_setkey_dec(ctx, keyBytes);
  170. byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, new BASE64Decoder().decodeBuffer(cipherText));
  171. return new String(decrypted, “GBK”);
  172. }
  173. catch (Exception e)
  174. {
  175. e.printStackTrace();
  176. return null;
  177. }
  178. }
  179. public static void main(String[] args) throws IOException
  180. {
  181. String plainText = “ererfeiisgod”;
  182. SM4Utils sm4 = new SM4Utils();
  183. sm4.secretKey = “JeF8U9wHFOMfs2Y8”;
  184. sm4.hexString = false;
  185. System.out.println(“ECB模式加密”);
  186. String cipherText = sm4.encryptData_ECB(plainText);
  187. System.out.println(“密文: “ + cipherText);
  188. System.out.println(“”);
  189. plainText = sm4.decryptData_ECB(cipherText);
  190. System.out.println(“明文: “ + plainText);
  191. System.out.println(“”);
  192. System.out.println(“CBC模式加密”);
  193. sm4.iv = “UISwD9fW6cFh9SNS”;
  194. cipherText = sm4.encryptData_CBC(plainText);
  195. System.out.println(“密文: “ + cipherText);
  196. System.out.println(“”);
  197. plainText = sm4.decryptData_CBC(cipherText);
  198. System.out.println(“明文: “ + plainText);
  199. System.out.println(“CBC模式解密”);
  200. System.out.println(“密文:4esGgDn/snKraRDe6uM0jQ==”);
  201. String cipherText2 = “4esGgDn/snKraRDe6uM0jQ==”;
  202. plainText = sm4.decryptData_CBC(cipherText2);
  203. System.out.println(“明文: “ + plainText);
  204. }
  205. }

Utils.java

  1. import java.math.BigInteger;
  2. public class Util {
  3. /**
  4. * 整形转换成网络传输的字节流(字节数组)型数据
  5. *
  6. * @param num 一个整型数据
  7. * @return 4个字节的自己数组
  8. */
  9. public static byte[] intToBytes(int num)
  10. {
  11. byte[] bytes = new byte[4];
  12. bytes[0] = (byte) (0xff & (num >> 0));
  13. bytes[1] = (byte) (0xff & (num >> 8));
  14. bytes[2] = (byte) (0xff & (num >> 16));
  15. bytes[3] = (byte) (0xff & (num >> 24));
  16. return bytes;
  17. }
  18. /**
  19. * 四个字节的字节数据转换成一个整形数据
  20. *
  21. * @param bytes 4个字节的字节数组
  22. * @return 一个整型数据
  23. */
  24. public static int byteToInt(byte[] bytes)
  25. {
  26. int num = 0;
  27. int temp;
  28. temp = (0x000000ff & (bytes[0])) << 0;
  29. num = num | temp;
  30. temp = (0x000000ff & (bytes[1])) << 8;
  31. num = num | temp;
  32. temp = (0x000000ff & (bytes[2])) << 16;
  33. num = num | temp;
  34. temp = (0x000000ff & (bytes[3])) << 24;
  35. num = num | temp;
  36. return num;
  37. }
  38. /**
  39. * 长整形转换成网络传输的字节流(字节数组)型数据
  40. *
  41. * @param num 一个长整型数据
  42. * @return 4个字节的自己数组
  43. */
  44. public static byte[] longToBytes(long num)
  45. {
  46. byte[] bytes = new byte[8];
  47. for (int i = 0; i < 8; i++)
  48. {
  49. bytes[i] = (byte) (0xff & (num >> (i * 8)));
  50. }
  51. return bytes;
  52. }
  53. /**
  54. * 大数字转换字节流(字节数组)型数据
  55. *
  56. * @param n
  57. * @return
  58. */
  59. public static byte[] byteConvert32Bytes(BigInteger n)
  60. {
  61. byte tmpd[] = (byte[])null;
  62. if(n == null)
  63. {
  64. return null;
  65. }
  66. if(n.toByteArray().length == 33)
  67. {
  68. tmpd = new byte[32];
  69. System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);
  70. }
  71. else if(n.toByteArray().length == 32)
  72. {
  73. tmpd = n.toByteArray();
  74. }
  75. else
  76. {
  77. tmpd = new byte[32];
  78. for(int i = 0; i < 32 – n.toByteArray().length; i++)
  79. {
  80. tmpd[i] = 0;
  81. }
  82. System.arraycopy(n.toByteArray(), 0, tmpd, 32 – n.toByteArray().length, n.toByteArray().length);
  83. }
  84. return tmpd;
  85. }
  86. /**
  87. * 换字节流(字节数组)型数据转大数字
  88. *
  89. * @param b
  90. * @return
  91. */
  92. public static BigInteger byteConvertInteger(byte[] b)
  93. {
  94. if (b[0] < 0)
  95. {
  96. byte[] temp = new byte[b.length + 1];
  97. temp[0] = 0;
  98. System.arraycopy(b, 0, temp, 1, b.length);
  99. return new BigInteger(temp);
  100. }
  101. return new BigInteger(b);
  102. }
  103. /**
  104. * 根据字节数组获得值(十六进制数字)
  105. *
  106. * @param bytes
  107. * @return
  108. */
  109. public static String getHexString(byte[] bytes)
  110. {
  111. return getHexString(bytes, true);
  112. }
  113. /**
  114. * 根据字节数组获得值(十六进制数字)
  115. *
  116. * @param bytes
  117. * @param upperCase
  118. * @return
  119. */
  120. public static String getHexString(byte[] bytes, boolean upperCase)
  121. {
  122. String ret = “”;
  123. for (int i = 0; i < bytes.length; i++)
  124. {
  125. ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);
  126. }
  127. return upperCase ? ret.toUpperCase() : ret;
  128. }
  129. /**
  130. * 打印十六进制字符串
  131. *
  132. * @param bytes
  133. */
  134. public static void printHexString(byte[] bytes)
  135. {
  136. for (int i = 0; i < bytes.length; i++)
  137. {
  138. String hex = Integer.toHexString(bytes[i] & 0xFF);
  139. if (hex.length() == 1)
  140. {
  141. hex = ‘0’ + hex;
  142. }
  143. System.out.print(“0x” + hex.toUpperCase() + “,”);
  144. }
  145. System.out.println(“”);
  146. }
  147. /**
  148. * Convert hex string to byte[]
  149. *
  150. * @param hexString
  151. * the hex string
  152. * @return byte[]
  153. */
  154. public static byte[] hexStringToBytes(String hexString)
  155. {
  156. if (hexString == null || hexString.equals(“”))
  157. {
  158. return null;
  159. }
  160. hexString = hexString.toUpperCase();
  161. int length = hexString.length() / 2;
  162. char[] hexChars = hexString.toCharArray();
  163. byte[] d = new byte[length];
  164. for (int i = 0; i < length; i++)
  165. {
  166. int pos = i * 2;
  167. d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
  168. }
  169. return d;
  170. }
  171. /**
  172. * Convert char to byte
  173. *
  174. * @param c
  175. * char
  176. * @return byte
  177. */
  178. public static byte charToByte(char c)
  179. {
  180. return (byte) “0123456789ABCDEF”.indexOf(c);
  181. }
  182. /**
  183. * 用于建立十六进制字符的输出的小写字符数组
  184. */
  185. private static final char[] DIGITS_LOWER = {‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’,
  186. ‘6’, ‘7’, ‘8’, ‘9’, ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’};
  187. /**
  188. * 用于建立十六进制字符的输出的大写字符数组
  189. */
  190. private static final char[] DIGITS_UPPER = {‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’,
  191. ‘6’, ‘7’, ‘8’, ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’};
  192. /**
  193. * 将字节数组转换为十六进制字符数组
  194. *
  195. * @param data byte[]
  196. * @return 十六进制char[]
  197. */
  198. public static char[] encodeHex(byte[] data) {
  199. return encodeHex(data, true);
  200. }
  201. /**
  202. * 将字节数组转换为十六进制字符数组
  203. *
  204. * @param data byte[]
  205. * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
  206. * @return 十六进制char[]
  207. */
  208. public static char[] encodeHex(byte[] data, boolean toLowerCase) {
  209. return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
  210. }
  211. /**
  212. * 将字节数组转换为十六进制字符数组
  213. *
  214. * @param data byte[]
  215. * @param toDigits 用于控制输出的char[]
  216. * @return 十六进制char[]
  217. */
  218. protected static char[] encodeHex(byte[] data, char[] toDigits) {
  219. int l = data.length;
  220. char[] out = new char[l << 1];
  221. // two characters form the hex value.
  222. for (int i = 0, j = 0; i < l; i++) {
  223. out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
  224. out[j++] = toDigits[0x0F & data[i]];
  225. }
  226. return out;
  227. }
  228. /**
  229. * 将字节数组转换为十六进制字符串
  230. *
  231. * @param data byte[]
  232. * @return 十六进制String
  233. */
  234. public static String encodeHexString(byte[] data) {
  235. return encodeHexString(data, true);
  236. }
  237. /**
  238. * 将字节数组转换为十六进制字符串
  239. *
  240. * @param data byte[]
  241. * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
  242. * @return 十六进制String
  243. */
  244. public static String encodeHexString(byte[] data, boolean toLowerCase) {
  245. return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
  246. }
  247. /**
  248. * 将字节数组转换为十六进制字符串
  249. *
  250. * @param data byte[]
  251. * @param toDigits 用于控制输出的char[]
  252. * @return 十六进制String
  253. */
  254. protected static String encodeHexString(byte[] data, char[] toDigits) {
  255. return new String(encodeHex(data, toDigits));
  256. }
  257. /**
  258. * 将十六进制字符数组转换为字节数组
  259. *
  260. * @param data 十六进制char[]
  261. * @return byte[]
  262. * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
  263. */
  264. public static byte[] decodeHex(char[] data) {
  265. int len = data.length;
  266. if ((len & 0x01) != 0) {
  267. throw new RuntimeException(“Odd number of characters.”);
  268. }
  269. byte[] out = new byte[len >> 1];
  270. // two characters form the hex value.
  271. for (int i = 0, j = 0; j < len; i++) {
  272. int f = toDigit(data[j], j) << 4;
  273. j++;
  274. f = f | toDigit(data[j], j);
  275. j++;
  276. out[i] = (byte) (f & 0xFF);
  277. }
  278. return out;
  279. }
  280. /**
  281. * 将十六进制字符转换成一个整数
  282. *
  283. * @param ch 十六进制char
  284. * @param index 十六进制字符在字符数组中的位置
  285. * @return 一个整数
  286. * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
  287. */
  288. protected static int toDigit(char ch, int index) {
  289. int digit = Character.digit(ch, 16);
  290. if (digit == –1) {
  291. throw new RuntimeException(“Illegal hexadecimal character “ + ch
  292. + ” at index “ + index);
  293. }
  294. return digit;
  295. }
  296. /**
  297. * 数字字符串转ASCII码字符串
  298. *
  299. * @param String
  300. * 字符串
  301. * @return ASCII字符串
  302. */
  303. public static String StringToAsciiString(String content) {
  304. String result = “”;
  305. int max = content.length();
  306. for (int i = 0; i < max; i++) {
  307. char c = content.charAt(i);
  308. String b = Integer.toHexString(c);
  309. result = result + b;
  310. }
  311. return result;
  312. }
  313. /**
  314. * 十六进制转字符串
  315. *
  316. * @param hexString
  317. * 十六进制字符串
  318. * @param encodeType
  319. * 编码类型4:Unicode,2:普通编码
  320. * @return 字符串
  321. */
  322. public static String hexStringToString(String hexString, int encodeType) {
  323. String result = “”;
  324. int max = hexString.length() / encodeType;
  325. for (int i = 0; i < max; i++) {
  326. char c = (char) hexStringToAlgorism(hexString
  327. .substring(i * encodeType, (i + 1) * encodeType));
  328. result += c;
  329. }
  330. return result;
  331. }
  332. /**
  333. * 十六进制字符串装十进制
  334. *
  335. * @param hex
  336. * 十六进制字符串
  337. * @return 十进制数值
  338. */
  339. public static int hexStringToAlgorism(String hex) {
  340. hex = hex.toUpperCase();
  341. int max = hex.length();
  342. int result = 0;
  343. for (int i = max; i > 0; i–) {
  344. char c = hex.charAt(i – 1);
  345. int algorism = 0;
  346. if (c >= ‘0’ && c <= ‘9’) {
  347. algorism = c – ‘0’;
  348. } else {
  349. algorism = c – 55;
  350. }
  351. result += Math.pow(16, max – i) * algorism;
  352. }
  353. return result;
  354. }
  355. /**
  356. * 十六转二进制
  357. *
  358. * @param hex
  359. * 十六进制字符串
  360. * @return 二进制字符串
  361. */
  362. public static String hexStringToBinary(String hex) {
  363. hex = hex.toUpperCase();
  364. String result = “”;
  365. int max = hex.length();
  366. for (int i = 0; i < max; i++) {
  367. char c = hex.charAt(i);
  368. switch (c) {
  369. case ‘0’:
  370. result += “0000”;
  371. break;
  372. case ‘1’:
  373. result += “0001”;
  374. break;
  375. case ‘2’:
  376. result += “0010”;
  377. break;
  378. case ‘3’:
  379. result += “0011”;
  380. break;
  381. case ‘4’:
  382. result += “0100”;
  383. break;
  384. case ‘5’:
  385. result += “0101”;
  386. break;
  387. case ‘6’:
  388. result += “0110”;
  389. break;
  390. case ‘7’:
  391. result += “0111”;
  392. break;
  393. case ‘8’:
  394. result += “1000”;
  395. break;
  396. case ‘9’:
  397. result += “1001”;
  398. break;
  399. case ‘A’:
  400. result += “1010”;
  401. break;
  402. case ‘B’:
  403. result += “1011”;
  404. break;
  405. case ‘C’:
  406. result += “1100”;
  407. break;
  408. case ‘D’:
  409. result += “1101”;
  410. break;
  411. case ‘E’:
  412. result += “1110”;
  413. break;
  414. case ‘F’:
  415. result += “1111”;
  416. break;
  417. }
  418. }
  419. return result;
  420. }
  421. /**
  422. * ASCII码字符串转数字字符串
  423. *
  424. * @param String
  425. * ASCII字符串
  426. * @return 字符串
  427. */
  428. public static String AsciiStringToString(String content) {
  429. String result = “”;
  430. int length = content.length() / 2;
  431. for (int i = 0; i < length; i++) {
  432. String c = content.substring(i * 2, i * 2 + 2);
  433. int a = hexStringToAlgorism(c);
  434. char b = (char) a;
  435. String d = String.valueOf(b);
  436. result += d;
  437. }
  438. return result;
  439. }
  440. /**
  441. * 将十进制转换为指定长度的十六进制字符串
  442. *
  443. * @param algorism
  444. * int 十进制数字
  445. * @param maxLength
  446. * int 转换后的十六进制字符串长度
  447. * @return String 转换后的十六进制字符串
  448. */
  449. public static String algorismToHexString(int algorism, int maxLength) {
  450. String result = “”;
  451. result = Integer.toHexString(algorism);
  452. if (result.length() % 2 == 1) {
  453. result = “0” + result;
  454. }
  455. return patchHexString(result.toUpperCase(), maxLength);
  456. }
  457. /**
  458. * 字节数组转为普通字符串(ASCII对应的字符)
  459. *
  460. * @param bytearray
  461. * byte[]
  462. * @return String
  463. */
  464. public static String byteToString(byte[] bytearray) {
  465. String result = “”;
  466. char temp;
  467. int length = bytearray.length;
  468. for (int i = 0; i < length; i++) {
  469. temp = (char) bytearray[i];
  470. result += temp;
  471. }
  472. return result;
  473. }
  474. /**
  475. * 二进制字符串转十进制
  476. *
  477. * @param binary
  478. * 二进制字符串
  479. * @return 十进制数值
  480. */
  481. public static int binaryToAlgorism(String binary) {
  482. int max = binary.length();
  483. int result = 0;
  484. for (int i = max; i > 0; i–) {
  485. char c = binary.charAt(i – 1);
  486. int algorism = c – ‘0’;
  487. result += Math.pow(2, max – i) * algorism;
  488. }
  489. return result;
  490. }
  491. /**
  492. * 十进制转换为十六进制字符串
  493. *
  494. * @param algorism
  495. * int 十进制的数字
  496. * @return String 对应的十六进制字符串
  497. */
  498. public static String algorismToHEXString(int algorism) {
  499. String result = “”;
  500. result = Integer.toHexString(algorism);
  501. if (result.length() % 2 == 1) {
  502. result = “0” + result;
  503. }
  504. result = result.toUpperCase();
  505. return result;
  506. }
  507. /**
  508. * HEX字符串前补0,主要用于长度位数不足。
  509. *
  510. * @param str
  511. * String 需要补充长度的十六进制字符串
  512. * @param maxLength
  513. * int 补充后十六进制字符串的长度
  514. * @return 补充结果
  515. */
  516. static public String patchHexString(String str, int maxLength) {
  517. String temp = “”;
  518. for (int i = 0; i < maxLength – str.length(); i++) {
  519. temp = “0” + temp;
  520. }
  521. str = (temp + str).substring(0, maxLength);
  522. return str;
  523. }
  524. /**
  525. * 将一个字符串转换为int
  526. *
  527. * @param s
  528. * String 要转换的字符串
  529. * @param defaultInt
  530. * int 如果出现异常,默认返回的数字
  531. * @param radix
  532. * int 要转换的字符串是什么进制的,如16 8 10.
  533. * @return int 转换后的数字
  534. */
  535. public static int parseToInt(String s, int defaultInt, int radix) {
  536. int i = 0;
  537. try {
  538. i = Integer.parseInt(s, radix);
  539. } catch (NumberFormatException ex) {
  540. i = defaultInt;
  541. }
  542. return i;
  543. }
  544. /**
  545. * 将一个十进制形式的数字字符串转换为int
  546. *
  547. * @param s
  548. * String 要转换的字符串
  549. * @param defaultInt
  550. * int 如果出现异常,默认返回的数字
  551. * @return int 转换后的数字
  552. */
  553. public static int parseToInt(String s, int defaultInt) {
  554. int i = 0;
  555. try {
  556. i = Integer.parseInt(s);
  557. } catch (NumberFormatException ex) {
  558. i = defaultInt;
  559. }
  560. return i;
  561. }
  562. /**
  563. * 十六进制串转化为byte数组
  564. *
  565. * @return the array of byte
  566. */
  567. public static byte[] hexToByte(String hex)
  568. throws IllegalArgumentException {
  569. if (hex.length() % 2 != 0) {
  570. throw new IllegalArgumentException();
  571. }
  572. char[] arr = hex.toCharArray();
  573. byte[] b = new byte[hex.length() / 2];
  574. for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
  575. String swap = “” + arr[i++] + arr[i];
  576. int byteint = Integer.parseInt(swap, 16) & 0xFF;
  577. b[j] = new Integer(byteint).byteValue();
  578. }
  579. return b;
  580. }
  581. /**
  582. * 字节数组转换为十六进制字符串
  583. *
  584. * @param b
  585. * byte[] 需要转换的字节数组
  586. * @return String 十六进制字符串
  587. */
  588. public static String byteToHex(byte b[]) {
  589. if (b == null) {
  590. throw new IllegalArgumentException(
  591. “Argument b ( byte array ) is null! “);
  592. }
  593. String hs = “”;
  594. String stmp = “”;
  595. for (int n = 0; n < b.length; n++) {
  596. stmp = Integer.toHexString(b[n] & 0xff);
  597. if (stmp.length() == 1) {
  598. hs = hs + “0” + stmp;
  599. } else {
  600. hs = hs + stmp;
  601. }
  602. }
  603. return hs.toUpperCase();
  604. }
  605. public static byte[] subByte(byte[] input, int startIndex, int length) {
  606. byte[] bt = new byte[length];
  607. for (int i = 0; i < length; i++) {
  608. bt[i] = input[i + startIndex];
  609. }
  610. return bt;
  611. }
  612. }
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享