SM3.java 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package com.ydtech.utils;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.IOException;
  4. import java.math.BigInteger;
  5. import java.util.Arrays;
  6. /**
  7. * SM3杂凑算法实现
  8. */
  9. public class SM3 {
  10. private static char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
  11. '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  12. private static final String ivHexStr = "7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e";
  13. private static final BigInteger IV = new BigInteger(ivHexStr.replaceAll(" ",
  14. ""), 16);
  15. private static final Integer Tj15 = Integer.valueOf("79cc4519", 16);
  16. private static final Integer Tj63 = Integer.valueOf("7a879d8a", 16);
  17. private static final byte[] FirstPadding = {(byte) 0x80};
  18. private static final byte[] ZeroPadding = {(byte) 0x00};
  19. private static int T(int j) {
  20. if (j >= 0 && j <= 15) {
  21. return Tj15.intValue();
  22. } else if (j >= 16 && j <= 63) {
  23. return Tj63.intValue();
  24. } else {
  25. throw new RuntimeException("data invalid");
  26. }
  27. }
  28. private static Integer FF(Integer x, Integer y, Integer z, int j) {
  29. if (j >= 0 && j <= 15) {
  30. return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());
  31. } else if (j >= 16 && j <= 63) {
  32. return Integer.valueOf((x.intValue() & y.intValue())
  33. | (x.intValue() & z.intValue())
  34. | (y.intValue() & z.intValue()));
  35. } else {
  36. throw new RuntimeException("data invalid");
  37. }
  38. }
  39. private static Integer GG(Integer x, Integer y, Integer z, int j) {
  40. if (j >= 0 && j <= 15) {
  41. return Integer.valueOf(x.intValue() ^ y.intValue() ^ z.intValue());
  42. } else if (j >= 16 && j <= 63) {
  43. return Integer.valueOf((x.intValue() & y.intValue())
  44. | (~x.intValue() & z.intValue()));
  45. } else {
  46. throw new RuntimeException("data invalid");
  47. }
  48. }
  49. private static Integer P0(Integer x) {
  50. return Integer.valueOf(x.intValue()
  51. ^ Integer.rotateLeft(x.intValue(), 9)
  52. ^ Integer.rotateLeft(x.intValue(), 17));
  53. }
  54. private static Integer P1(Integer x) {
  55. return Integer.valueOf(x.intValue()
  56. ^ Integer.rotateLeft(x.intValue(), 15)
  57. ^ Integer.rotateLeft(x.intValue(), 23));
  58. }
  59. private static byte[] padding(byte[] source) throws IOException {
  60. if (source.length >= 0x2000000000000000l) {
  61. throw new RuntimeException("src data invalid.");
  62. }
  63. long l = source.length * 8;
  64. long k = 448 - (l + 1) % 512;
  65. if (k < 0) {
  66. k = k + 512;
  67. }
  68. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  69. baos.write(source);
  70. baos.write(FirstPadding);
  71. long i = k - 7;
  72. while (i > 0) {
  73. baos.write(ZeroPadding);
  74. i -= 8;
  75. }
  76. baos.write(long2bytes(l));
  77. return baos.toByteArray();
  78. }
  79. private static byte[] long2bytes(long l) {
  80. byte[] bytes = new byte[8];
  81. for (int i = 0; i < 8; i++) {
  82. bytes[i] = (byte) (l >>> ((7 - i) * 8));
  83. }
  84. return bytes;
  85. }
  86. public static byte[] hash(byte[] source) throws IOException {
  87. byte[] m1 = padding(source);
  88. int n = m1.length / (512 / 8);
  89. byte[] b;
  90. byte[] vi = IV.toByteArray();
  91. byte[] vi1 = null;
  92. for (int i = 0; i < n; i++) {
  93. b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);
  94. vi1 = CF(vi, b);
  95. vi = vi1;
  96. }
  97. return vi1;
  98. }
  99. private static byte[] CF(byte[] vi, byte[] bi) throws IOException {
  100. int a, b, c, d, e, f, g, h;
  101. a = toInteger(vi, 0);
  102. b = toInteger(vi, 1);
  103. c = toInteger(vi, 2);
  104. d = toInteger(vi, 3);
  105. e = toInteger(vi, 4);
  106. f = toInteger(vi, 5);
  107. g = toInteger(vi, 6);
  108. h = toInteger(vi, 7);
  109. int[] w = new int[68];
  110. int[] w1 = new int[64];
  111. for (int i = 0; i < 16; i++) {
  112. w[i] = toInteger(bi, i);
  113. }
  114. for (int j = 16; j < 68; j++) {
  115. w[j] = P1(w[j - 16] ^ w[j - 9] ^ Integer.rotateLeft(w[j - 3], 15))
  116. ^ Integer.rotateLeft(w[j - 13], 7) ^ w[j - 6];
  117. }
  118. for (int j = 0; j < 64; j++) {
  119. w1[j] = w[j] ^ w[j + 4];
  120. }
  121. int ss1, ss2, tt1, tt2;
  122. for (int j = 0; j < 64; j++) {
  123. ss1 = Integer
  124. .rotateLeft(
  125. Integer.rotateLeft(a, 12) + e
  126. + Integer.rotateLeft(T(j), j), 7);
  127. ss2 = ss1 ^ Integer.rotateLeft(a, 12);
  128. tt1 = FF(a, b, c, j) + d + ss2 + w1[j];
  129. tt2 = GG(e, f, g, j) + h + ss1 + w[j];
  130. d = c;
  131. c = Integer.rotateLeft(b, 9);
  132. b = a;
  133. a = tt1;
  134. h = g;
  135. g = Integer.rotateLeft(f, 19);
  136. f = e;
  137. e = P0(tt2);
  138. }
  139. byte[] v = toByteArray(a, b, c, d, e, f, g, h);
  140. for (int i = 0; i < v.length; i++) {
  141. v[i] = (byte) (v[i] ^ vi[i]);
  142. }
  143. return v;
  144. }
  145. private static int toInteger(byte[] source, int index) {
  146. StringBuilder valueStr = new StringBuilder("");
  147. for (int i = 0; i < 4; i++) {
  148. valueStr.append(hexDigits[(byte) ((source[index * 4 + i] & 0xF0) >> 4)]);
  149. valueStr.append(hexDigits[(byte) (source[index * 4 + i] & 0x0F)]);
  150. }
  151. return Long.valueOf(valueStr.toString(), 16).intValue();
  152. }
  153. private static byte[] toByteArray(int a, int b, int c, int d, int e, int f,
  154. int g, int h) throws IOException {
  155. ByteArrayOutputStream baos = new ByteArrayOutputStream(32);
  156. baos.write(toByteArray(a));
  157. baos.write(toByteArray(b));
  158. baos.write(toByteArray(c));
  159. baos.write(toByteArray(d));
  160. baos.write(toByteArray(e));
  161. baos.write(toByteArray(f));
  162. baos.write(toByteArray(g));
  163. baos.write(toByteArray(h));
  164. return baos.toByteArray();
  165. }
  166. public static byte[] toByteArray(int i) {
  167. byte[] byteArray = new byte[4];
  168. byteArray[0] = (byte) (i >>> 24);
  169. byteArray[1] = (byte) ((i & 0xFFFFFF) >>> 16);
  170. byteArray[2] = (byte) ((i & 0xFFFF) >>> 8);
  171. byteArray[3] = (byte) (i & 0xFF);
  172. return byteArray;
  173. }
  174. private static String byteToHexString(byte b) {
  175. int n = b;
  176. if (n < 0) {
  177. n = 256 + n;
  178. }
  179. int d1 = n / 16;
  180. int d2 = n % 16;
  181. return "" + hexDigits[d1] + hexDigits[d2];
  182. }
  183. public static String byteArrayToHexString(byte[] b) {
  184. StringBuffer resultSb = new StringBuffer();
  185. for (int i = 0; i < b.length; i++) {
  186. resultSb.append(byteToHexString(b[i]));
  187. }
  188. return resultSb.toString();
  189. }
  190. public static void main(String[] args) throws IOException {
  191. System.out.println(SM3.byteArrayToHexString(SM3.hash("sm3算法测试".getBytes())));
  192. }
  193. }