JAVA國密加密演算法的實現方法

【摘要】

本文主要講解「國密加密演算法」SM系列的Java實現方法,不涉及具體的演算法剖析,在網路上找到的java實現方法比較少,且在跨語言加密解密上會存在一些問題,所以整理此文,希望對大家有所幫助。

1.SM2 & SM3

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

項目目錄結構如下:

首先要下載一個jar包——bcprov-jdk.jar,可以到maven庫中下載最新版http://central.maven.org/maven2/org/bouncycastle/並將該jar包引入項目的classpath。實現代碼如下(每個工具類都有Main可以運行測試):

A. SM2主類

【SM2.java】

[java] view plain copy

  1. package com.mlq.sm;

  2. import java.math.BigInteger;

  3. import java.security.SecureRandom;

  4. importorg.bouncycastle.crypto.generators.ECKeyPairGenerator;

  5. import org.bouncycastle.crypto.params.ECDomainParameters;

  6. importorg.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. publicclass 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. publicstatic String[] ecc_param = {

  24. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",

  25. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",

  26. "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",

  27. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",

  28. "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",

  29. "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"

  30. };

  31. publicstatic SM2 Instance()

  32. {

  33. returnnew SM2();

  34. }

  35. publicfinal BigInteger ecc_p;

  36. publicfinal BigInteger ecc_a;

  37. publicfinal BigInteger ecc_b;

  38. publicfinal BigInteger ecc_n;

  39. publicfinal BigInteger ecc_gx;

  40. publicfinal BigInteger ecc_gy;

  41. publicfinal ECCurve ecc_curve;

  42. publicfinal ECPoint ecc_point_g;

  43. publicfinal ECDomainParameters ecc_bc_spec;

  44. publicfinal ECKeyPairGenerator ecc_key_pair_generator;

  45. publicfinal ECFieldElement ecc_gx_fieldelement;

  46. publicfinal 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】

[java] view plain copy

  1. package com.mlq.sm;

  2. import java.io.IOException;

  3. import java.math.BigInteger;

  4. import org.bouncycastle.crypto.AsymmetricCipherKeyPair;

  5. importorg.bouncycastle.crypto.params.ECPrivateKeyParameters;

  6. import org.bouncycastle.crypto.params.ECPublicKeyParameters;

  7. import org.bouncycastle.math.ec.ECPoint;

  8. publicclass SM2Utils

  9. {

  10. //生成隨機秘鑰對

  11. publicstaticvoid 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. publicstatic String encrypt(byte[] publicKey, byte[] data)throws IOException

  23. {

  24. if (publicKey == null || publicKey.length == 0)

  25. {

  26. returnnull;

  27. }

  28. if (data == null || data.length == 0)

  29. {

  30. returnnull;

  31. }

  32. byte[] source = newbyte[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 = newbyte[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. publicstaticbyte[] decrypt(byte[] privateKey, byte[]encryptedData) throws IOException

  49. {

  50. if (privateKey == null || privateKey.length == 0)

  51. {

  52. returnnull;

  53. }

  54. if (encryptedData == null || encryptedData.length == 0)

  55. {

  56. returnnull;

  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. publicstaticvoid 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】

[java] view plain copy

  1. package com.mlq.sm;

  2. publicclass SM3

  3. {

  4. publicstaticfinalbyte[] iv = { 0x73, (byte) 0x80, 0x16, 0x6f,0x49,

  5. 0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte)0xd7,

  6. (byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f,0x30,

  7. (byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte)0xe3,

  8. (byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb,0x0e,

  9. 0x4e };

  10. publicstaticint[] Tj = newint[64];

  11. static

  12. {

  13. for (int i = 0; i < 16; i++)

  14. {

  15. Tj[i] = 0x79cc4519;

  16. }

  17. for (int i = 16; i < 64; i++)

  18. {

  19. Tj[i] = 0x7a879d8a;

  20. }

  21. }

  22. publicstaticbyte[] CF(byte[] V, byte[] B)

  23. {

  24. int[] v, b;

  25. v = convert(V);

  26. b = convert(B);

  27. return convert(CF(v, b));

  28. }

  29. privatestaticint[] convert(byte[] arr)

  30. {

  31. int[] out = newint[arr.length / 4];

  32. byte[] tmp = newbyte[4];

  33. for (int i = 0; i < arr.length; i += 4)

  34. {

  35. System.arraycopy(arr, i, tmp, 0, 4);

  36. out[i / 4] = bigEndianByteToInt(tmp);

  37. }

  38. return out;

  39. }

  40. privatestaticbyte[] convert(int[] arr)

  41. {

  42. byte[] out = newbyte[arr.length * 4];

  43. byte[] tmp = null;

  44. for (int i = 0; i < arr.length; i++)

  45. {

  46. tmp = bigEndianIntToByte(arr[i]);

  47. System.arraycopy(tmp, 0, out, i * 4, 4);

  48. }

  49. return out;

  50. }

  51. publicstaticint[] CF(int[] V, int[] B)

  52. {

  53. int a, b, c, d, e, f, g, h;

  54. int ss1, ss2, tt1, tt2;

  55. a = V[0];

  56. b = V[1];

  57. c = V[2];

  58. d = V[3];

  59. e = V[4];

  60. f = V[5];

  61. g = V[6];

  62. h = V[7];

  63. int[][] arr = expand(B);

  64. int[] w = arr[0];

  65. int[] w1 = arr[1];

  66. for (int j = 0; j < 64; j++)

  67. {

  68. ss1 = (bitCycleLeft(a, 12) + e + bitCycleLeft(Tj[j], j));

  69. ss1 = bitCycleLeft(ss1, 7);

  70. ss2 = ss1 ^ bitCycleLeft(a, 12);

  71. tt1 = FFj(a, b, c, j) + d + ss2 + w1[j];

  72. tt2 = GGj(e, f, g, j) + h + ss1 + w[j];

  73. d = c;

  74. c = bitCycleLeft(b, 9);

  75. b = a;

  76. a = tt1;

  77. h = g;

  78. g = bitCycleLeft(f, 19);

  79. f = e;

  80. e = P0(tt2);

  81. }

  82. // System.out.println("");

  83. int[] out = newint[8];

  84. out[0] = a ^ V[0];

  85. out[1] = b ^ V[1];

  86. out[2] = c ^ V[2];

  87. out[3] = d ^ V[3];

  88. out[4] = e ^ V[4];

  89. out[5] = f ^ V[5];

  90. out[6] = g ^ V[6];

  91. out[7] = h ^ V[7];

  92. return out;

  93. }

  94. privatestaticint[][] expand(int[] B)

  95. {

  96. int W[] = newint[68];

  97. int W1[] = newint[64];

  98. for (int i = 0; i < B.length; i++)

  99. {

  100. W[i] = B[i];

  101. }

  102. for (int i = 16; i < 68; i++)

  103. {

  104. W[i] = P1(W[i - 16] ^ W[i - 9] ^ bitCycleLeft(W[i - 3], 15))

  105. ^ bitCycleLeft(W[i - 13], 7) ^ W[i - 6];

  106. }

  107. for (int i = 0; i < 64; i++)

  108. {

  109. W1[i] = W[i] ^ W[i + 4];

  110. }

  111. int arr[][] = newint[][] { W, W1 };

  112. return arr;

  113. }

  114. privatestaticbyte[] bigEndianIntToByte(int num)

  115. {

  116. return back(Util.intToBytes(num));

  117. }

  118. privatestaticint bigEndianByteToInt(byte[] bytes)

  119. {

  120. return Util.byteToInt(back(bytes));

  121. }

  122. privatestaticint FFj(int X, int Y, int Z, int j)

  123. {

  124. if (j >= 0 && j <= 15)

  125. {

  126. return FF1j(X, Y, Z);

  127. }

  128. else

  129. {

  130. return FF2j(X, Y, Z);

  131. }

  132. }

  133. privatestaticint GGj(int X, int Y, int Z, int j)

  134. {

  135. if (j >= 0 && j <= 15)

  136. {

  137. return GG1j(X, Y, Z);

  138. }

  139. else

  140. {

  141. return GG2j(X, Y, Z);

  142. }

  143. }

  144. // 邏輯位運算函數

  145. privatestaticint FF1j(int X, int Y, int Z)

  146. {

  147. int tmp = X ^ Y ^ Z;

  148. return tmp;

  149. }

  150. privatestaticint FF2j(int X, int Y, int Z)

  151. {

  152. int tmp = ((X & Y) | (X & Z) | (Y & Z));

  153. return tmp;

  154. }

  155. privatestaticint GG1j(int X, int Y, int Z)

  156. {

  157. int tmp = X ^ Y ^ Z;

  158. return tmp;

  159. }

  160. privatestaticint GG2j(int X, int Y, int Z)

  161. {

  162. int tmp = (X & Y) | (~X & Z);

  163. return tmp;

  164. }

  165. privatestaticint P0(int X)

  166. {

  167. int y = rotateLeft(X, 9);

  168. y = bitCycleLeft(X, 9);

  169. int z = rotateLeft(X, 17);

  170. z = bitCycleLeft(X, 17);

  171. int t = X ^ y ^ z;

  172. return t;

  173. }

  174. privatestaticint P1(int X)

  175. {

  176. int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23);

  177. return t;

  178. }

  179. /**

  180. * 對最後一個分組位元組數據padding

  181. *

  182. * @param in

  183. * @param bLen

  184. * 分組個數

  185. * @return

  186. */

  187. publicstaticbyte[] padding(byte[] in, int bLen)

  188. {

  189. int k = 448 - (8 * in.length + 1) % 512;

  190. if (k < 0)

  191. {

  192. k = 960 - (8 * in.length + 1) % 512;

  193. }

  194. k += 1;

  195. byte[] padd = newbyte[k / 8];

  196. padd[0] = (byte) 0x80;

  197. long n = in.length * 8 + bLen * 512;

  198. byte[] out = newbyte[in.length + k / 8 + 64 / 8];

  199. int pos = 0;

  200. System.arraycopy(in, 0, out, 0, in.length);

  201. pos += in.length;

  202. System.arraycopy(padd, 0, out, pos, padd.length);

  203. pos += padd.length;

  204. byte[] tmp = back(Util.longToBytes(n));

  205. System.arraycopy(tmp, 0, out, pos, tmp.length);

  206. return out;

  207. }

  208. /**

  209. * 位元組數組逆序

  210. *

  211. * @param in

  212. * @return

  213. */

  214. privatestaticbyte[] back(byte[] in)

  215. {

  216. byte[] out = newbyte[in.length];

  217. for (int i = 0; i < out.length; i++)

  218. {

  219. out[i] = in[out.length - i - 1];

  220. }

  221. return out;

  222. }

  223. publicstaticint rotateLeft(int x, int n)

  224. {

  225. return (x << n) | (x >> (32 - n));

  226. }

  227. privatestaticint bitCycleLeft(int n, int bitLen)

  228. {

  229. bitLen %= 32;

  230. byte[] tmp = bigEndianIntToByte(n);

  231. int byteLen = bitLen / 8;

  232. int len = bitLen % 8;

  233. if (byteLen > 0)

  234. {

  235. tmp = byteCycleLeft(tmp, byteLen);

  236. }

  237. if (len > 0)

  238. {

  239. tmp = bitSmall8CycleLeft(tmp, len);

  240. }

  241. return bigEndianByteToInt(tmp);

  242. }

  243. privatestaticbyte[] bitSmall8CycleLeft(byte[] in, int len)

  244. {

  245. byte[] tmp = newbyte[in.length];

  246. int t1, t2, t3;

  247. for (int i = 0; i < tmp.length; i++)

  248. {

  249. t1 = (byte) ((in[i] & 0x000000ff) << len);

  250. t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff)>> (8 - len));

  251. t3 = (byte) (t1 | t2);

  252. tmp[i] = (byte) t3;

  253. }

  254. return tmp;

  255. }

  256. privatestaticbyte[] byteCycleLeft(byte[] in, int byteLen)

  257. {

  258. byte[] tmp = newbyte[in.length];

  259. System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen);

  260. System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen);

  261. return tmp;

  262. }

  263. }

D. SM3工具類

【SM3Digest.java】

[java] view plain copy

  1. package com.mlq.sm;

  2. import org.bouncycastle.util.encoders.Hex;

  3. publicclass SM3Digest

  4. {

  5. /** SM3值的長度 */

  6. privatestaticfinalint BYTE_LENGTH = 32;

  7. /** SM3分組長度 */

  8. privatestaticfinalint BLOCK_LENGTH = 64;

  9. /** 緩衝區長度 */

  10. privatestaticfinalint BUFFER_LENGTH = BLOCK_LENGTH * 1;

  11. /** 緩衝區 */

  12. privatebyte[] xBuf = newbyte[BUFFER_LENGTH];

  13. /** 緩衝區偏移量 */

  14. privateint xBufOff;

  15. /** 初始向量 */

  16. privatebyte[] V = SM3.iv.clone();

  17. privateint cntBlock = 0;

  18. public SM3Digest() {

  19. }

  20. public SM3Digest(SM3Digest t)

  21. {

  22. System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);

  23. this.xBufOff = t.xBufOff;

  24. System.arraycopy(t.V, 0, this.V, 0, t.V.length);

  25. }

  26. /**

  27. * SM3結果輸出

  28. *

  29. * @param out 保存SM3結構的緩衝區

  30. * @param outOff 緩衝區偏移量

  31. * @return

  32. */

  33. publicint doFinal(byte[] out, int outOff)

  34. {

  35. byte[] tmp = doFinal();

  36. System.arraycopy(tmp, 0, out, 0, tmp.length);

  37. return BYTE_LENGTH;

  38. }

  39. publicvoid reset()

  40. {

  41. xBufOff = 0;

  42. cntBlock = 0;

  43. V = SM3.iv.clone();

  44. }

  45. /**

  46. * 明文輸入

  47. *

  48. * @param in

  49. * 明文輸入緩衝區

  50. * @param inOff

  51. * 緩衝區偏移量

  52. * @param len

  53. * 明文長度

  54. */

  55. publicvoid update(byte[] in, int inOff, int len)

  56. {

  57. int partLen = BUFFER_LENGTH - xBufOff;

  58. int inputLen = len;

  59. int dPos = inOff;

  60. if (partLen < inputLen)

  61. {

  62. System.arraycopy(in, dPos, xBuf, xBufOff, partLen);

  63. inputLen -= partLen;

  64. dPos += partLen;

  65. doUpdate();

  66. while (inputLen > BUFFER_LENGTH)

  67. {

  68. System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH);

  69. inputLen -= BUFFER_LENGTH;

  70. dPos += BUFFER_LENGTH;

  71. doUpdate();

  72. }

  73. }

  74. System.arraycopy(in, dPos, xBuf, xBufOff, inputLen);

  75. xBufOff += inputLen;

  76. }

  77. privatevoid doUpdate()

  78. {

  79. byte[] B = newbyte[BLOCK_LENGTH];

  80. for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH)

  81. {

  82. System.arraycopy(xBuf, i, B, 0, B.length);

  83. doHash(B);

  84. }

  85. xBufOff = 0;

  86. }

  87. privatevoid doHash(byte[] B)

  88. {

  89. byte[] tmp = SM3.CF(V, B);

  90. System.arraycopy(tmp, 0, V, 0, V.length);

  91. cntBlock++;

  92. }

  93. privatebyte[] doFinal()

  94. {

  95. byte[] B = newbyte[BLOCK_LENGTH];

  96. byte[] buffer = newbyte[xBufOff];

  97. System.arraycopy(xBuf, 0, buffer, 0, buffer.length);

  98. byte[] tmp = SM3.padding(buffer, cntBlock);

  99. for (int i = 0; i < tmp.length; i += BLOCK_LENGTH)

  100. {

  101. System.arraycopy(tmp, i, B, 0, B.length);

  102. doHash(B);

  103. }

  104. return V;

  105. }

  106. publicvoid update(byte in)

  107. {

  108. byte[] buffer = newbyte[] { in };

  109. update(buffer, 0, 1);

  110. }

  111. publicint getDigestSize()

  112. {

  113. return BYTE_LENGTH;

  114. }

  115. publicstaticvoid main(String[] args)

  116. {

  117. byte[] md = newbyte[32];

  118. byte[] msg1 = "ererfeiisgod".getBytes();

  119. SM3Digest sm3 = new SM3Digest();

  120. sm3.update(msg1, 0, msg1.length);

  121. sm3.doFinal(md, 0);

  122. String s = new String(Hex.encode(md));

  123. System.out.println(s.toUpperCase());

  124. }

  125. }

E. 工具類

【Util.java】

[java] view plain copy

  1. package com.mlq.sm;

  2. import java.math.BigInteger;

  3. publicclass Util

  4. {

  5. /**

  6. * 整形轉換成網路傳輸的位元組流(位元組數組)型數據

  7. *

  8. * @param num 一個整型數據

  9. * @return 4個位元組的自己數組

  10. */

  11. publicstaticbyte[] intToBytes(int num)

  12. {

  13. byte[] bytes = newbyte[4];

  14. bytes[0] = (byte) (0xff & (num >> 0));

  15. bytes[1] = (byte) (0xff & (num >> 8));

  16. bytes[2] = (byte) (0xff & (num >> 16));

  17. bytes[3] = (byte) (0xff & (num >> 24));

  18. return bytes;

  19. }

  20. /**

  21. * 四個位元組的位元組數據轉換成一個整形數據

  22. *

  23. * @param bytes 4個位元組的位元組數組

  24. * @return 一個整型數據

  25. */

  26. publicstaticint byteToInt(byte[] bytes)

  27. {

  28. int num = 0;

  29. int temp;

  30. temp = (0x000000ff & (bytes[0])) << 0;

  31. num = num | temp;

  32. temp = (0x000000ff & (bytes[1])) << 8;

  33. num = num | temp;

  34. temp = (0x000000ff & (bytes[2])) << 16;

  35. num = num | temp;

  36. temp = (0x000000ff & (bytes[3])) << 24;

  37. num = num | temp;

  38. return num;

  39. }

  40. /**

  41. * 長整形轉換成網路傳輸的位元組流(位元組數組)型數據

  42. *

  43. * @param num 一個長整型數據

  44. * @return 4個位元組的自己數組

  45. */

  46. publicstaticbyte[] longToBytes(long num)

  47. {

  48. byte[] bytes = newbyte[8];

  49. for (int i = 0; i < 8; i++)

  50. {

  51. bytes[i] = (byte) (0xff & (num >> (i * 8)));

  52. }

  53. return bytes;

  54. }

  55. /**

  56. * 大數字轉換位元組流(位元組數組)型數據

  57. *

  58. * @param n

  59. * @return

  60. */

  61. publicstaticbyte[] byteConvert32Bytes(BigInteger n)

  62. {

  63. byte tmpd[] = (byte[])null;

  64. if(n == null)

  65. {

  66. returnnull;

  67. }

  68. if(n.toByteArray().length == 33)

  69. {

  70. tmpd = newbyte[32];

  71. System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);

  72. }

  73. elseif(n.toByteArray().length == 32)

  74. {

  75. tmpd = n.toByteArray();

  76. }

  77. else

  78. {

  79. tmpd = newbyte[32];

  80. for(int i = 0; i < 32 - n.toByteArray().length; i++)

  81. {

  82. tmpd[i] = 0;

  83. }

  84. System.arraycopy(n.toByteArray(), 0, tmpd, 32 -n.toByteArray().length, n.toByteArray().length);

  85. }

  86. return tmpd;

  87. }

  88. /**

  89. * 換位元組流(位元組數組)型數據轉大數字

  90. *

  91. * @param b

  92. * @return

  93. */

  94. publicstatic BigInteger byteConvertInteger(byte[] b)

  95. {

  96. if (b[0] < 0)

  97. {

  98. byte[] temp = newbyte[b.length + 1];

  99. temp[0] = 0;

  100. System.arraycopy(b, 0, temp, 1, b.length);

  101. returnnew BigInteger(temp);

  102. }

  103. returnnew BigInteger(b);

  104. }

  105. /**

  106. * 根據位元組數組獲得值(十六進位數字)

  107. *

  108. * @param bytes

  109. * @return

  110. */

  111. publicstatic String getHexString(byte[] bytes)

  112. {

  113. return getHexString(bytes, true);

  114. }

  115. /**

  116. * 根據位元組數組獲得值(十六進位數字)

  117. *

  118. * @param bytes

  119. * @param upperCase

  120. * @return

  121. */

  122. publicstatic String getHexString(byte[] bytes, booleanupperCase)

  123. {

  124. String ret = "";

  125. for (int i = 0; i < bytes.length; i++)

  126. {

  127. ret += Integer.toString((bytes[i] & 0xff) + 0x100,16).substring(1);

  128. }

  129. return upperCase ? ret.toUpperCase() : ret;

  130. }

  131. /**

  132. * 列印十六進位字元串

  133. *

  134. * @param bytes

  135. */

  136. publicstaticvoid printHexString(byte[] bytes)

  137. {

  138. for (int i = 0; i < bytes.length; i++)

  139. {

  140. String hex = Integer.toHexString(bytes[i] & 0xFF);

  141. if (hex.length() == 1)

  142. {

  143. hex = '0' + hex;

  144. }

  145. System.out.print("0x" + hex.toUpperCase() + ",");

  146. }

  147. System.out.println("");

  148. }

  149. /**

  150. * Convert hex string to byte[]

  151. *

  152. * @param hexString

  153. * the hex string

  154. * @return byte[]

  155. */

  156. publicstaticbyte[] hexStringToBytes(String hexString)

  157. {

  158. if (hexString == null || hexString.equals(""))

  159. {

  160. returnnull;

  161. }

  162. hexString = hexString.toUpperCase();

  163. int length = hexString.length() / 2;

  164. char[] hexChars = hexString.toCharArray();

  165. byte[] d = newbyte[length];

  166. for (int i = 0; i < length; i++)

  167. {

  168. int pos = i * 2;

  169. d[i] = (byte) (charToByte(hexChars[pos]) << 4 |charToByte(hexChars[pos + 1]));

  170. }

  171. return d;

  172. }

  173. /**

  174. * Convert char to byte

  175. *

  176. * @param c

  177. * char

  178. * @return byte

  179. */

  180. publicstaticbyte charToByte(char c)

  181. {

  182. return (byte) "0123456789ABCDEF".indexOf(c);

  183. }

  184. /**

  185. * 用於建立十六進位字元的輸出的小寫字元數組

  186. */

  187. privatestaticfinalchar[] DIGITS_LOWER = {'0', '1', '2', '3','4', '5',

  188. '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

  189. /**

  190. * 用於建立十六進位字元的輸出的大寫字元數組

  191. */

  192. privatestaticfinalchar[] DIGITS_UPPER = {'0', '1', '2', '3','4', '5',

  193. '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

  194. /**

  195. * 將位元組數組轉換為十六進位字元數組

  196. *

  197. * @param data byte[]

  198. * @return 十六進位char[]

  199. */

  200. publicstaticchar[] encodeHex(byte[] data) {

  201. return encodeHex(data, true);

  202. }

  203. /**

  204. * 將位元組數組轉換為十六進位字元數組

  205. *

  206. * @param data byte[]

  207. * @param toLowerCase <code>true</code> 傳換成小寫格式 ,<code>false</code> 傳換成大寫格式

  208. * @return 十六進位char[]

  209. */

  210. publicstaticchar[] encodeHex(byte[] data, boolean toLowerCase){

  211. return encodeHex(data, toLowerCase ? DIGITS_LOWER :DIGITS_UPPER);

  212. }

  213. /**

  214. * 將位元組數組轉換為十六進位字元數組

  215. *

  216. * @param data byte[]

  217. * @param toDigits 用於控制輸出的char[]

  218. * @return 十六進位char[]

  219. */

  220. protectedstaticchar[] encodeHex(byte[] data, char[] toDigits){

  221. int l = data.length;

  222. char[] out = newchar[l << 1];

  223. // two characters form the hex value.

  224. for (int i = 0, j = 0; i < l; i++) {

  225. out[j++] = toDigits[(0xF0 & data[i]) >>> 4];

  226. out[j++] = toDigits[0x0F & data[i]];

  227. }

  228. return out;

  229. }

  230. /**

  231. * 將位元組數組轉換為十六進位字元串

  232. *

  233. * @param data byte[]

  234. * @return 十六進位String

  235. */

  236. publicstatic String encodeHexString(byte[] data) {

  237. return encodeHexString(data, true);

  238. }

  239. /**

  240. * 將位元組數組轉換為十六進位字元串

  241. *

  242. * @param data byte[]

  243. * @param toLowerCase <code>true</code> 傳換成小寫格式 ,<code>false</code> 傳換成大寫格式

  244. * @return 十六進位String

  245. */

  246. publicstatic String encodeHexString(byte[] data, booleantoLowerCase) {

  247. return encodeHexString(data, toLowerCase ? DIGITS_LOWER :DIGITS_UPPER);

  248. }

  249. /**

  250. * 將位元組數組轉換為十六進位字元串

  251. *

  252. * @param data byte[]

  253. * @param toDigits 用於控制輸出的char[]

  254. * @return 十六進位String

  255. */

  256. protectedstatic String encodeHexString(byte[] data, char[]toDigits) {

  257. returnnew String(encodeHex(data, toDigits));

  258. }

  259. /**

  260. * 將十六進位字元數組轉換為位元組數組

  261. *

  262. * @param data 十六進位char[]

  263. * @return byte[]

  264. * @throws RuntimeException 如果源十六進位字元數組是一個奇怪的長度,將拋出運行時異常

  265. */

  266. publicstaticbyte[] decodeHex(char[] data) {

  267. int len = data.length;

  268. if ((len & 0x01) != 0) {

  269. thrownew RuntimeException("Odd number of characters.");

  270. }

  271. byte[] out = newbyte[len >> 1];

  272. // two characters form the hex value.

  273. for (int i = 0, j = 0; j < len; i++) {

  274. int f = toDigit(data[j], j) << 4;

  275. j++;

  276. f = f | toDigit(data[j], j);

  277. j++;

  278. out[i] = (byte) (f & 0xFF);

  279. }

  280. return out;

  281. }

  282. /**

  283. * 將十六進位字元轉換成一個整數

  284. *

  285. * @param ch 十六進位char

  286. * @param index 十六進位字元在字元數組中的位置

  287. * @return 一個整數

  288. * @throws RuntimeException 當ch不是一個合法的十六進位字元時,拋出運行時異常

  289. */

  290. protectedstaticint toDigit(char ch, int index) {

  291. int digit = Character.digit(ch, 16);

  292. if (digit == -1) {

  293. thrownew RuntimeException("Illegal hexadecimal character " +ch

  294. + " at index " + index);

  295. }

  296. return digit;

  297. }

  298. /**

  299. * 數字字元串轉ASCII碼字元串

  300. *

  301. * @param String

  302. * 字元串

  303. * @return ASCII字元串

  304. */

  305. publicstatic String StringToAsciiString(String content) {

  306. String result = "";

  307. int max = content.length();

  308. for (int i = 0; i < max; i++) {

  309. char c = content.charAt(i);

  310. String b = Integer.toHexString(c);

  311. result = result + b;

  312. }

  313. return result;

  314. }

  315. /**

  316. * 十六進位轉字元串

  317. *

  318. * @param hexString

  319. * 十六進位字元串

  320. * @param encodeType

  321. * 編碼類型4:Unicode,2:普通編碼

  322. * @return 字元串

  323. */

  324. publicstatic String hexStringToString(String hexString, intencodeType) {

  325. String result = "";

  326. int max = hexString.length() / encodeType;

  327. for (int i = 0; i < max; i++) {

  328. char c = (char) hexStringToAlgorism(hexString

  329. .substring(i * encodeType, (i + 1) * encodeType));

  330. result += c;

  331. }

  332. return result;

  333. }

  334. /**

  335. * 十六進位字元串裝十進位

  336. *

  337. * @param hex

  338. * 十六進位字元串

  339. * @return 十進位數值

  340. */

  341. publicstaticint hexStringToAlgorism(String hex) {

  342. hex = hex.toUpperCase();

  343. int max = hex.length();

  344. int result = 0;

  345. for (int i = max; i > 0; i--) {

  346. char c = hex.charAt(i - 1);

  347. int algorism = 0;

  348. if (c >= '0' && c <= '9') {

  349. algorism = c - '0';

  350. } else {

  351. algorism = c - 55;

  352. }

  353. result += Math.pow(16, max - i) * algorism;

  354. }

  355. return result;

  356. }

  357. /**

  358. * 十六轉二進位

  359. *

  360. * @param hex

  361. * 十六進位字元串

  362. * @return 二進位字元串

  363. */

  364. publicstatic String hexStringToBinary(String hex) {

  365. hex = hex.toUpperCase();

  366. String result = "";

  367. int max = hex.length();

  368. for (int i = 0; i < max; i++) {

  369. char c = hex.charAt(i);

  370. switch (c) {

  371. case'0':

  372. result += "0000";

  373. break;

  374. case'1':

  375. result += "0001";

  376. break;

  377. case'2':

  378. result += "0010";

  379. break;

  380. case'3':

  381. result += "0011";

  382. break;

  383. case'4':

  384. result += "0100";

  385. break;

  386. case'5':

  387. result += "0101";

  388. break;

  389. case'6':

  390. result += "0110";

  391. break;

  392. case'7':

  393. result += "0111";

  394. break;

  395. case'8':

  396. result += "1000";

  397. break;

  398. case'9':

  399. result += "1001";

  400. break;

  401. case'A':

  402. result += "1010";

  403. break;

  404. case'B':

  405. result += "1011";

  406. break;

  407. case'C':

  408. result += "1100";

  409. break;

  410. case'D':

  411. result += "1101";

  412. break;

  413. case'E':

  414. result += "1110";

  415. break;

  416. case'F':

  417. result += "1111";

  418. break;

  419. }

  420. }

  421. return result;

  422. }

  423. /**

  424. * ASCII碼字元串轉數字字元串

  425. *

  426. * @param String

  427. * ASCII字元串

  428. * @return 字元串

  429. */

  430. publicstatic String AsciiStringToString(String content) {

  431. String result = "";

  432. int length = content.length() / 2;

  433. for (int i = 0; i < length; i++) {

  434. String c = content.substring(i * 2, i * 2 + 2);

  435. int a = hexStringToAlgorism(c);

  436. char b = (char) a;

  437. String d = String.valueOf(b);

  438. result += d;

  439. }

  440. return result;

  441. }

  442. /**

  443. * 將十進位轉換為指定長度的十六進位字元串

  444. *

  445. * @param algorism

  446. * int 十進位數字

  447. * @param maxLength

  448. * int 轉換后的十六進位字元串長度

  449. * @return String 轉換后的十六進位字元串

  450. */

  451. publicstatic String algorismToHexString(int algorism, intmaxLength) {

  452. String result = "";

  453. result = Integer.toHexString(algorism);

  454. if (result.length() % 2 == 1) {

  455. result = "0" + result;

  456. }

  457. return patchHexString(result.toUpperCase(), maxLength);

  458. }

  459. /**

  460. * 位元組數組轉為普通字元串(ASCII對應的字元)

  461. *

  462. * @param bytearray

  463. * byte[]

  464. * @return String

  465. */

  466. publicstatic String byteToString(byte[] bytearray) {

  467. String result = "";

  468. char temp;

  469. int length = bytearray.length;

  470. for (int i = 0; i < length; i++) {

  471. temp = (char) bytearray[i];

  472. result += temp;

  473. }

  474. return result;

  475. }

  476. /**

  477. * 二進位字元串轉十進位

  478. *

  479. * @param binary

  480. * 二進位字元串

  481. * @return 十進位數值

  482. */

  483. publicstaticint binaryToAlgorism(String binary) {

  484. int max = binary.length();

  485. int result = 0;

  486. for (int i = max; i > 0; i--) {

  487. char c = binary.charAt(i - 1);

  488. int algorism = c - '0';

  489. result += Math.pow(2, max - i) * algorism;

  490. }

  491. return result;

  492. }

  493. /**

  494. * 十進位轉換為十六進位字元串

  495. *

  496. * @param algorism

  497. * int 十進位的數字

  498. * @return String 對應的十六進位字元串

  499. */

  500. publicstatic String algorismToHEXString(int algorism) {

  501. String result = "";

  502. result = Integer.toHexString(algorism);

  503. if (result.length() % 2 == 1) {

  504. result = "0" + result;

  505. }

  506. result = result.toUpperCase();

  507. return result;

  508. }

  509. /**

  510. * HEX字元串前補0,主要用於長度位數不足。

  511. *

  512. * @param str

  513. * String 需要補充長度的十六進位字元串

  514. * @param maxLength

  515. * int 補充后十六進位字元串的長度

  516. * @return 補充結果

  517. */

  518. staticpublic String patchHexString(String str, int maxLength){

  519. String temp = "";

  520. for (int i = 0; i < maxLength - str.length(); i++) {

  521. temp = "0" + temp;

  522. }

  523. str = (temp + str).substring(0, maxLength);

  524. return str;

  525. }

  526. /**

  527. * 將一個字元串轉換為int

  528. *

  529. * @param s

  530. * String 要轉換的字元串

  531. * @param defaultInt

  532. * int 如果出現異常,默認返回的數字

  533. * @param radix

  534. * int 要轉換的字元串是什麼進位的,如16 8 10.

  535. * @return int 轉換后的數字

  536. */

  537. publicstaticint parseToInt(String s, int defaultInt, int radix){

  538. int i = 0;

  539. try {

  540. i = Integer.parseInt(s, radix);

  541. } catch (NumberFormatException ex) {

  542. i = defaultInt;

  543. }

  544. return i;

  545. }

  546. /**

  547. * 將一個十進位形式的數字字元串轉換為int

  548. *

  549. * @param s

  550. * String 要轉換的字元串

  551. * @param defaultInt

  552. * int 如果出現異常,默認返回的數字

  553. * @return int 轉換后的數字

  554. */

  555. publicstaticint parseToInt(String s, int defaultInt) {

  556. int i = 0;

  557. try {

  558. i = Integer.parseInt(s);

  559. } catch (NumberFormatException ex) {

  560. i = defaultInt;

  561. }

  562. return i;

  563. }

  564. /**

  565. * 十六進位串轉化為byte數組

  566. *

  567. * @return the array of byte

  568. */

  569. publicstaticbyte[] hexToByte(String hex)

  570. throws IllegalArgumentException {

  571. if (hex.length() % 2 != 0) {

  572. thrownew IllegalArgumentException();

  573. }

  574. char[] arr = hex.toCharArray();

  575. byte[] b = newbyte[hex.length() / 2];

  576. for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++){

  577. String swap = "" + arr[i++] + arr[i];

  578. int byteint = Integer.parseInt(swap, 16) & 0xFF;

  579. b[j] = new Integer(byteint).byteValue();

  580. }

  581. return b;

  582. }

  583. /**

  584. * 位元組數組轉換為十六進位字元串

  585. *

  586. * @param b

  587. * byte[] 需要轉換的位元組數組

  588. * @return String 十六進位字元串

  589. */

  590. publicstatic String byteToHex(byte b[]) {

  591. if (b == null) {

  592. thrownew IllegalArgumentException(

  593. "Argument b ( byte array ) is null! ");

  594. }

  595. String hs = "";

  596. String stmp = "";

  597. for (int n = 0; n < b.length; n++) {

  598. stmp = Integer.toHexString(b[n] & 0xff);

  599. if (stmp.length() == 1) {

  600. hs = hs + "0" + stmp;

  601. } else {

  602. hs = hs + stmp;

  603. }

  604. }

  605. return hs.toUpperCase();

  606. }

  607. publicstaticbyte[] subByte(byte[] input, int startIndex, intlength) {

  608. byte[] bt = newbyte[length];

  609. for (int i = 0; i < length; i++) {

  610. bt[i] = input[i + startIndex];

  611. }

  612. return bt;

  613. }

  614. }

F. Chiper類

[java] view plain copy

  1. package com.mlq.sm;

  2. import java.math.BigInteger;

  3. import org.bouncycastle.crypto.AsymmetricCipherKeyPair;

  4. importorg.bouncycastle.crypto.params.ECPrivateKeyParameters;

  5. import org.bouncycastle.crypto.params.ECPublicKeyParameters;

  6. import org.bouncycastle.math.ec.ECPoint;

  7. publicclass Cipher

  8. {

  9. privateint ct;

  10. private ECPoint p2;

  11. private SM3Digest sm3keybase;

  12. private SM3Digest sm3c3;

  13. privatebyte key[];

  14. privatebyte keyOff;

  15. public Cipher()

  16. {

  17. this.ct = 1;

  18. this.key = newbyte[32];

  19. this.keyOff = 0;

  20. }

  21. privatevoid Reset()

  22. {

  23. this.sm3keybase = new SM3Digest();

  24. this.sm3c3 = new SM3Digest();

  25. byte p[] =Util.byteConvert32Bytes(p2.getX().toBigInteger());

  26. this.sm3keybase.update(p, 0, p.length);

  27. this.sm3c3.update(p, 0, p.length);

  28. p = Util.byteConvert32Bytes(p2.getY().toBigInteger());

  29. this.sm3keybase.update(p, 0, p.length);

  30. this.ct = 1;

  31. NextKey();

  32. }

  33. privatevoid NextKey()

  34. {

  35. SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);

  36. sm3keycur.update((byte) (ct >> 24 & 0xff));

  37. sm3keycur.update((byte) (ct >> 16 & 0xff));

  38. sm3keycur.update((byte) (ct >> 8 & 0xff));

  39. sm3keycur.update((byte) (ct & 0xff));

  40. sm3keycur.doFinal(key, 0);

  41. this.keyOff = 0;

  42. this.ct++;

  43. }

  44. public ECPoint Init_enc(SM2 sm2, ECPoint userKey)

  45. {

  46. AsymmetricCipherKeyPair key =sm2.ecc_key_pair_generator.generateKeyPair();

  47. ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.getPrivate();

  48. ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.getPublic();

  49. BigInteger k = ecpriv.getD();

  50. ECPoint c1 = ecpub.getQ();

  51. this.p2 = userKey.multiply(k);

  52. Reset();

  53. return c1;

  54. }

  55. publicvoid Encrypt(byte data[])

  56. {

  57. this.sm3c3.update(data, 0, data.length);

  58. for (int i = 0; i < data.length; i++)

  59. {

  60. if (keyOff == key.length)

  61. {

  62. NextKey();

  63. }

  64. data[i] ^= key[keyOff++];

  65. }

  66. }

  67. publicvoid Init_dec(BigInteger userD, ECPoint c1)

  68. {

  69. this.p2 = c1.multiply(userD);

  70. Reset();

  71. }

  72. publicvoid Decrypt(byte data[])

  73. {

  74. for (int i = 0; i < data.length; i++)

  75. {

  76. if (keyOff == key.length)

  77. {

  78. NextKey();

  79. }

  80. data[i] ^= key[keyOff++];

  81. }

  82. this.sm3c3.update(data, 0, data.length);

  83. }

  84. publicvoid Dofinal(byte c3[])

  85. {

  86. byte p[] =Util.byteConvert32Bytes(p2.getY().toBigInteger());

  87. this.sm3c3.update(p, 0, p.length);

  88. this.sm3c3.doFinal(c3, 0);

  89. Reset();

  90. }

  91. }

2.SM4

直接上代碼:

A. SM4主類

【SM4.java】

[java] view plain copy

  1. package com.mlq.sm;

  2. import java.io.ByteArrayInputStream;

  3. import java.io.ByteArrayOutputStream;

  4. publicclass SM4

  5. {

  6. publicstaticfinalint SM4_ENCRYPT = 1;

  7. publicstaticfinalint SM4_DECRYPT = 0;

  8. privatelong GET_ULONG_BE(byte[] b, int i)

  9. {

  10. 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;

  11. return n;

  12. }

  13. privatevoid PUT_ULONG_BE(long n, byte[] b, int i)

  14. {

  15. b[i] = (byte)(int)(0xFF & n >> 24);

  16. b[i + 1] = (byte)(int)(0xFF & n >> 16);

  17. b[i + 2] = (byte)(int)(0xFF & n >> 8);

  18. b[i + 3] = (byte)(int)(0xFF & n);

  19. }

  20. privatelong SHL(long x, int n)

  21. {

  22. return (x & 0xFFFFFFFF) << n;

  23. }

  24. privatelong ROTL(long x, int n)

  25. {

  26. return SHL(x, n) | x >> (32 - n);

  27. }

  28. privatevoid SWAP(long[] sk, int i)

  29. {

  30. long t = sk[i];

  31. sk[i] = sk[(31 - i)];

  32. sk[(31 - i)] = t;

  33. }

  34. publicstaticfinalbyte[] SboxTable = { (byte) 0xd6, (byte) 0x90,(byte) 0xe9, (byte) 0xfe,

  35. (byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte)0xb6,

  36. 0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b,0x67,

  37. (byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,

  38. (byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,

  39. (byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte)0x91,

  40. (byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,

  41. (byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,

  42. (byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte)0xe8,

  43. (byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte)0xfa,

  44. 0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte)0xa7,

  45. (byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte)0x83,

  46. 0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte)0xa8,

  47. 0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte)0xda,

  48. (byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70,0x56,

  49. (byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte)0xd1,

  50. (byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte)0x87,

  51. (byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3,0x27,

  52. 0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte)0xc4,

  53. (byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte)0x8a,

  54. (byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte)0xa3,

  55. (byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61,0x15,

  56. (byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,

  57. (byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93,0x32,

  58. 0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3,0x1d,

  59. (byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte)0xca,

  60. 0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e,0x6f,

  61. (byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte)0xfd,

  62. (byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c,0x5b,

  63. 0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte)0xbb,

  64. (byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c,0x41,

  65. 0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,

  66. (byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd,0x2d,

  67. 0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte)0xb4,

  68. (byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,

  69. (byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1,0x09,

  70. (byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte)0xf0,

  71. 0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,

  72. (byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48};

  73. publicstaticfinalint[] FK = { 0xa3b1bac6, 0x56aa3350,0x677d9197, 0xb27022dc };

  74. publicstaticfinalint[] CK = {0x00070e15,0x1c232a31,0x383f464d,0x545b6269,

  75. 0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,

  76. 0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,

  77. 0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,

  78. 0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,

  79. 0x30373e45,0x4c535a61,0x686f767d,0x848b9299,

  80. 0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,

  81. 0x10171e25,0x2c333a41,0x484f565d,0x646b7279 };

  82. privatebyte sm4Sbox(byte inch)

  83. {

  84. int i = inch & 0xFF;

  85. byte retVal = SboxTable[i];

  86. return retVal;

  87. }

  88. privatelong sm4Lt(long ka)

  89. {

  90. long bb = 0L;

  91. long c = 0L;

  92. byte[] a = newbyte[4];

  93. byte[] b = newbyte[4];

  94. PUT_ULONG_BE(ka, a, 0);

  95. b[0] = sm4Sbox(a[0]);

  96. b[1] = sm4Sbox(a[1]);

  97. b[2] = sm4Sbox(a[2]);

  98. b[3] = sm4Sbox(a[3]);

  99. bb = GET_ULONG_BE(b, 0);

  100. c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb,24);

  101. return c;

  102. }

  103. privatelong sm4F(long x0, long x1, long x2, long x3, longrk)

  104. {

  105. return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);

  106. }

  107. privatelong sm4CalciRK(long ka)

  108. {

  109. long bb = 0L;

  110. long rk = 0L;

  111. byte[] a = newbyte[4];

  112. byte[] b = newbyte[4];

  113. PUT_ULONG_BE(ka, a, 0);

  114. b[0] = sm4Sbox(a[0]);

  115. b[1] = sm4Sbox(a[1]);

  116. b[2] = sm4Sbox(a[2]);

  117. b[3] = sm4Sbox(a[3]);

  118. bb = GET_ULONG_BE(b, 0);

  119. rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);

  120. return rk;

  121. }

  122. privatevoid sm4_setkey(long[] SK, byte[] key)

  123. {

  124. long[] MK = newlong[4];

  125. long[] k = newlong[36];

  126. int i = 0;

  127. MK[0] = GET_ULONG_BE(key, 0);

  128. MK[1] = GET_ULONG_BE(key, 4);

  129. MK[2] = GET_ULONG_BE(key, 8);

  130. MK[3] = GET_ULONG_BE(key, 12);

  131. k[0] = MK[0] ^ (long) FK[0];

  132. k[1] = MK[1] ^ (long) FK[1];

  133. k[2] = MK[2] ^ (long) FK[2];

  134. k[3] = MK[3] ^ (long) FK[3];

  135. for (; i < 32; i++)

  136. {

  137. k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i +3)] ^ (long) CK[i]));

  138. SK[i] = k[(i + 4)];

  139. }

  140. }

  141. privatevoid sm4_one_round(long[] sk, byte[] input, byte[]output)

  142. {

  143. int i = 0;

  144. long[] ulbuf = newlong[36];

  145. ulbuf[0] = GET_ULONG_BE(input, 0);

  146. ulbuf[1] = GET_ULONG_BE(input, 4);

  147. ulbuf[2] = GET_ULONG_BE(input, 8);

  148. ulbuf[3] = GET_ULONG_BE(input, 12);

  149. while (i < 32)

  150. {

  151. ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)],ulbuf[(i + 3)], sk[i]);

  152. i++;

  153. }

  154. PUT_ULONG_BE(ulbuf[35], output, 0);

  155. PUT_ULONG_BE(ulbuf[34], output, 4);

  156. PUT_ULONG_BE(ulbuf[33], output, 8);

  157. PUT_ULONG_BE(ulbuf[32], output, 12);

  158. }

  159. privatebyte[] padding(byte[] input, int mode)

  160. {

  161. if (input == null)

  162. {

  163. returnnull;

  164. }

  165. byte[] ret = (byte[]) null;

  166. if (mode == SM4_ENCRYPT)

  167. {

  168. int p = 16 - input.length % 16;

  169. ret = newbyte[input.length + p];

  170. System.arraycopy(input, 0, ret, 0, input.length);

  171. for (int i = 0; i < p; i++)

  172. {

  173. ret[input.length + i] = (byte) p;

  174. }

  175. }

  176. else

  177. {

  178. int p = input[input.length - 1];

  179. ret = newbyte[input.length - p];

  180. System.arraycopy(input, 0, ret, 0, input.length - p);

  181. }

  182. return ret;

  183. }

  184. publicvoid sm4_setkey_enc(SM4_Context ctx, byte[] key) throwsException

  185. {

  186. if (ctx == null)

  187. {

  188. thrownew Exception("ctx is null!");

  189. }

  190. if (key == null || key.length != 16)

  191. {

  192. thrownew Exception("key error!");

  193. }

  194. ctx.mode = SM4_ENCRYPT;

  195. sm4_setkey(ctx.sk, key);

  196. }

  197. publicvoid sm4_setkey_dec(SM4_Context ctx, byte[] key) throwsException

  198. {

  199. if (ctx == null)

  200. {

  201. thrownew Exception("ctx is null!");

  202. }

  203. if (key == null || key.length != 16)

  204. {

  205. thrownew Exception("key error!");

  206. }

  207. int i = 0;

  208. ctx.mode = SM4_DECRYPT;

  209. sm4_setkey(ctx.sk, key);

  210. for (i = 0; i < 16; i++)

  211. {

  212. SWAP(ctx.sk, i);

  213. }

  214. }

  215. publicbyte[] sm4_crypt_ecb(SM4_Context ctx, byte[] input) throwsException

  216. {

  217. if (input == null)

  218. {

  219. thrownew Exception("input is null!");

  220. }

  221. if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT))

  222. {

  223. input = padding(input, SM4_ENCRYPT);

  224. }

  225. int length = input.length;

  226. ByteArrayInputStream bins = new ByteArrayInputStream(input);

  227. ByteArrayOutputStream bous = new ByteArrayOutputStream();

  228. for(; length > 0; length -= 16)

  229. {

  230. byte[] in = newbyte[16];

  231. byte[] out = newbyte[16];

  232. bins.read(in);

  233. sm4_one_round(ctx.sk, in, out);

  234. bous.write(out);

  235. }

  236. byte[] output = bous.toByteArray();

  237. if (ctx.isPadding && ctx.mode == SM4_DECRYPT)

  238. {

  239. output = padding(output, SM4_DECRYPT);

  240. }

  241. bins.close();

  242. bous.close();

  243. return output;

  244. }

  245. publicbyte[] sm4_crypt_cbc(SM4_Context ctx, byte[] iv, byte[]input) throws Exception

  246. {

  247. if (iv == null || iv.length != 16)

  248. {

  249. thrownew Exception("iv error!");

  250. }

  251. if (input == null)

  252. {

  253. thrownew Exception("input is null!");

  254. }

  255. if (ctx.isPadding && ctx.mode == SM4_ENCRYPT)

  256. {

  257. input = padding(input, SM4_ENCRYPT);

  258. }

  259. int i = 0;

  260. int length = input.length;

  261. ByteArrayInputStream bins = new ByteArrayInputStream(input);

  262. ByteArrayOutputStream bous = new ByteArrayOutputStream();

  263. if (ctx.mode == SM4_ENCRYPT)

  264. {

  265. for(; length > 0; length -= 16)

  266. {

  267. byte[] in = newbyte[16];

  268. byte[] out = newbyte[16];

  269. byte[] out1 = newbyte[16];

  270. bins.read(in);

  271. for (i = 0; i < 16; i++)

  272. {

  273. out[i] = ((byte) (in[i] ^ iv[i]));

  274. }

  275. sm4_one_round(ctx.sk, out, out1);

  276. System.arraycopy(out1, 0, iv, 0, 16);

  277. bous.write(out1);

  278. }

  279. }

  280. else

  281. {

  282. byte[] temp = newbyte[16];

  283. for(; length > 0; length -= 16)

  284. {

  285. byte[] in = newbyte[16];

  286. byte[] out = newbyte[16];

  287. byte[] out1 = newbyte[16];

  288. bins.read(in);

  289. System.arraycopy(in, 0, temp, 0, 16);

  290. sm4_one_round(ctx.sk, in, out);

  291. for (i = 0; i < 16; i++)

  292. {

  293. out1[i] = ((byte) (out[i] ^ iv[i]));

  294. }

  295. System.arraycopy(temp, 0, iv, 0, 16);

  296. bous.write(out1);

  297. }

  298. }

  299. byte[] output = bous.toByteArray();

  300. if (ctx.isPadding && ctx.mode == SM4_DECRYPT)

  301. {

  302. output = padding(output, SM4_DECRYPT);

  303. }

  304. bins.close();

  305. bous.close();

  306. return output;

  307. }

  308. }

B. SM4實體類

【SM4_Context.java】

[java] view plain copy

  1. package com.mlq.sm;

  2. publicclass SM4_Context

  3. {

  4. publicint mode;

  5. publiclong[] sk;

  6. publicboolean isPadding;

  7. public SM4_Context()

  8. {

  9. this.mode = 1;

  10. this.isPadding = true;

  11. this.sk = newlong[32];

  12. }

  13. }

C. SM4工具類(這裡的PaddingMode採用的是PKCS7)

【SM4Utils.java】

[java] view plain copy

  1. package com.mlq.sm;

  2. import java.io.IOException;

  3. import java.util.regex.Matcher;

  4. import java.util.regex.Pattern;

  5. import sun.misc.BASE64Decoder;

  6. import sun.misc.BASE64Encoder;

  7. publicclass SM4Utils

  8. {

  9. private String secretKey = "";

  10. private String iv = "";

  11. privateboolean hexString = false;

  12. public SM4Utils()

  13. {

  14. }

  15. public String encryptData_ECB(String plainText)

  16. {

  17. try

  18. {

  19. SM4_Context ctx = new SM4_Context();

  20. ctx.isPadding = true;

  21. ctx.mode = SM4.SM4_ENCRYPT;

  22. byte[] keyBytes;

  23. if (hexString)

  24. {

  25. keyBytes = Util.hexStringToBytes(secretKey);

  26. }

  27. else

  28. {

  29. keyBytes = secretKey.getBytes();

  30. }

  31. SM4 sm4 = new SM4();

  32. sm4.sm4_setkey_enc(ctx, keyBytes);

  33. byte[] encrypted = sm4.sm4_crypt_ecb(ctx,plainText.getBytes("GBK"));

  34. String cipherText = new BASE64Encoder().encode(encrypted);

  35. if (cipherText != null && cipherText.trim().length()> 0)

  36. {

  37. Pattern p = Pattern.compile("\\s*|\t|\r|\n");

  38. Matcher m = p.matcher(cipherText);

  39. cipherText = m.replaceAll("");

  40. }

  41. return cipherText;

  42. }

  43. catch (Exception e)

  44. {

  45. e.printStackTrace();

  46. returnnull;

  47. }

  48. }

  49. public String decryptData_ECB(String cipherText)

  50. {

  51. try

  52. {

  53. SM4_Context ctx = new SM4_Context();

  54. ctx.isPadding = true;

  55. ctx.mode = SM4.SM4_DECRYPT;

  56. byte[] keyBytes;

  57. if (hexString)

  58. {

  59. keyBytes = Util.hexStringToBytes(secretKey);

  60. }

  61. else

  62. {

  63. keyBytes = secretKey.getBytes();

  64. }

  65. SM4 sm4 = new SM4();

  66. sm4.sm4_setkey_dec(ctx, keyBytes);

  67. byte[] decrypted = sm4.sm4_crypt_ecb(ctx, newBASE64Decoder().decodeBuffer(cipherText));

  68. returnnew String(decrypted, "GBK");

  69. }

  70. catch (Exception e)

  71. {

  72. e.printStackTrace();

  73. returnnull;

  74. }

  75. }

  76. public String encryptData_CBC(String plainText)

  77. {

  78. try

  79. {

  80. SM4_Context ctx = new SM4_Context();

  81. ctx.isPadding = true;

  82. ctx.mode = SM4.SM4_ENCRYPT;

  83. byte[] keyBytes;

  84. byte[] ivBytes;

  85. if (hexString)

  86. {

  87. keyBytes = Util.hexStringToBytes(secretKey);

  88. ivBytes = Util.hexStringToBytes(iv);

  89. }

  90. else

  91. {

  92. keyBytes = secretKey.getBytes();

  93. ivBytes = iv.getBytes();

  94. }

  95. SM4 sm4 = new SM4();

  96. sm4.sm4_setkey_enc(ctx, keyBytes);

  97. byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes,plainText.getBytes("GBK"));

  98. String cipherText = new BASE64Encoder().encode(encrypted);

  99. if (cipherText != null && cipherText.trim().length()> 0)

  100. {

  101. Pattern p = Pattern.compile("\\s*|\t|\r|\n");

  102. Matcher m = p.matcher(cipherText);

  103. cipherText = m.replaceAll("");

  104. }

  105. return cipherText;

  106. }

  107. catch (Exception e)

  108. {

  109. e.printStackTrace();

  110. returnnull;

  111. }

  112. }

  113. public String decryptData_CBC(String cipherText)

  114. {

  115. try

  116. {

  117. SM4_Context ctx = new SM4_Context();

  118. ctx.isPadding = true;

  119. ctx.mode = SM4.SM4_DECRYPT;

  120. byte[] keyBytes;

  121. byte[] ivBytes;

  122. if (hexString)

  123. {

  124. keyBytes = Util.hexStringToBytes(secretKey);

  125. ivBytes = Util.hexStringToBytes(iv);

  126. }

  127. else

  128. {

  129. keyBytes = secretKey.getBytes();

  130. ivBytes = iv.getBytes();

  131. }

  132. SM4 sm4 = new SM4();

  133. sm4.sm4_setkey_dec(ctx, keyBytes);

  134. byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, newBASE64Decoder().decodeBuffer(cipherText));

  135. returnnew String(decrypted, "GBK");

  136. }

  137. catch (Exception e)

  138. {

  139. e.printStackTrace();

  140. returnnull;

  141. }

  142. }

  143. publicstaticvoid main(String[] args) throws IOException

  144. {

  145. String plainText = "ererfeiisgod";

  146. SM4Utils sm4 = new SM4Utils();

  147. sm4.secretKey = "JeF8U9wHFOMfs2Y8";

  148. sm4.hexString = false;

  149. System.out.println("ECB模式");

  150. String cipherText = sm4.encryptData_ECB(plainText);

  151. System.out.println("密文: " + cipherText);

  152. System.out.println("");

  153. plainText = sm4.decryptData_ECB(cipherText);

  154. System.out.println("明文: " + plainText);

  155. System.out.println("");

  156. System.out.println("CBC模式");

  157. sm4.iv = "UISwD9fW6cFh9SNS";

  158. cipherText = sm4.encryptData_CBC(plainText);

  159. System.out.println("密文: " + cipherText);

  160. System.out.println("");

  161. plainText = sm4.decryptData_CBC(cipherText);

  162. System.out.println("明文: " + plainText);

  163. }

  164. }

你可能會喜歡