001package top.cenze.utils.crypt.sm.sm3; 002 003import top.cenze.utils.ConvertUtil; 004 005/** 006 * Created by $(USER) on $(DATE) 007 */ 008public class SM3 { 009 public static final byte[] iv = { 0x73, (byte) 0x80, 0x16, 0x6f, 0x49, 010 0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte) 0xd7, 011 (byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30, 012 (byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte) 0xe3, 013 (byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb, 0x0e, 014 0x4e }; 015 016 public static int[] Tj = new int[64]; 017 018 static 019 { 020 for (int i = 0; i < 16; i++) 021 { 022 Tj[i] = 0x79cc4519; 023 } 024 025 for (int i = 16; i < 64; i++) 026 { 027 Tj[i] = 0x7a879d8a; 028 } 029 } 030 031 public static byte[] CF(byte[] V, byte[] B) 032 { 033 int[] v, b; 034 v = convert(V); 035 b = convert(B); 036 return convert(CF(v, b)); 037 } 038 039 private static int[] convert(byte[] arr) 040 { 041 int[] out = new int[arr.length / 4]; 042 byte[] tmp = new byte[4]; 043 for (int i = 0; i < arr.length; i += 4) 044 { 045 System.arraycopy(arr, i, tmp, 0, 4); 046 out[i / 4] = bigEndianByteToInt(tmp); 047 } 048 return out; 049 } 050 051 private static byte[] convert(int[] arr) 052 { 053 byte[] out = new byte[arr.length * 4]; 054 byte[] tmp = null; 055 for (int i = 0; i < arr.length; i++) 056 { 057 tmp = bigEndianIntToByte(arr[i]); 058 System.arraycopy(tmp, 0, out, i * 4, 4); 059 } 060 return out; 061 } 062 063 public static int[] CF(int[] V, int[] B) 064 { 065 int a, b, c, d, e, f, g, h; 066 int ss1, ss2, tt1, tt2; 067 a = V[0]; 068 b = V[1]; 069 c = V[2]; 070 d = V[3]; 071 e = V[4]; 072 f = V[5]; 073 g = V[6]; 074 h = V[7]; 075 076 int[][] arr = expand(B); 077 int[] w = arr[0]; 078 int[] w1 = arr[1]; 079 080 for (int j = 0; j < 64; j++) 081 { 082 ss1 = (bitCycleLeft(a, 12) + e + bitCycleLeft(Tj[j], j)); 083 ss1 = bitCycleLeft(ss1, 7); 084 ss2 = ss1 ^ bitCycleLeft(a, 12); 085 tt1 = FFj(a, b, c, j) + d + ss2 + w1[j]; 086 tt2 = GGj(e, f, g, j) + h + ss1 + w[j]; 087 d = c; 088 c = bitCycleLeft(b, 9); 089 b = a; 090 a = tt1; 091 h = g; 092 g = bitCycleLeft(f, 19); 093 f = e; 094 e = P0(tt2); 095 096 /*System.out.print(j+" "); 097 System.out.print(Integer.toHexString(a)+" "); 098 System.out.print(Integer.toHexString(b)+" "); 099 System.out.print(Integer.toHexString(c)+" "); 100 System.out.print(Integer.toHexString(d)+" "); 101 System.out.print(Integer.toHexString(e)+" "); 102 System.out.print(Integer.toHexString(f)+" "); 103 System.out.print(Integer.toHexString(g)+" "); 104 System.out.print(Integer.toHexString(h)+" "); 105 System.out.println("");*/ 106 } 107// System.out.println(""); 108 109 int[] out = new int[8]; 110 out[0] = a ^ V[0]; 111 out[1] = b ^ V[1]; 112 out[2] = c ^ V[2]; 113 out[3] = d ^ V[3]; 114 out[4] = e ^ V[4]; 115 out[5] = f ^ V[5]; 116 out[6] = g ^ V[6]; 117 out[7] = h ^ V[7]; 118 119 return out; 120 } 121 122 private static int[][] expand(int[] B) 123 { 124 int W[] = new int[68]; 125 int W1[] = new int[64]; 126 for (int i = 0; i < B.length; i++) 127 { 128 W[i] = B[i]; 129 } 130 131 for (int i = 16; i < 68; i++) 132 { 133 W[i] = P1(W[i - 16] ^ W[i - 9] ^ bitCycleLeft(W[i - 3], 15)) 134 ^ bitCycleLeft(W[i - 13], 7) ^ W[i - 6]; 135 } 136 137 for (int i = 0; i < 64; i++) 138 { 139 W1[i] = W[i] ^ W[i + 4]; 140 } 141 142 int arr[][] = new int[][] { W, W1 }; 143 return arr; 144 } 145 146 private static byte[] bigEndianIntToByte(int num) 147 { 148 return back(ConvertUtil.intToBytes(num)); 149 } 150 151 private static int bigEndianByteToInt(byte[] bytes) 152 { 153 return ConvertUtil.byteToInt(back(bytes)); 154 } 155 156 private static int FFj(int X, int Y, int Z, int j) 157 { 158 if (j >= 0 && j <= 15) 159 { 160 return FF1j(X, Y, Z); 161 } 162 else 163 { 164 return FF2j(X, Y, Z); 165 } 166 } 167 168 private static int GGj(int X, int Y, int Z, int j) 169 { 170 if (j >= 0 && j <= 15) 171 { 172 return GG1j(X, Y, Z); 173 } 174 else 175 { 176 return GG2j(X, Y, Z); 177 } 178 } 179 180 // 逻辑位运算函数 181 private static int FF1j(int X, int Y, int Z) 182 { 183 int tmp = X ^ Y ^ Z; 184 return tmp; 185 } 186 187 private static int FF2j(int X, int Y, int Z) 188 { 189 int tmp = ((X & Y) | (X & Z) | (Y & Z)); 190 return tmp; 191 } 192 193 private static int GG1j(int X, int Y, int Z) 194 { 195 int tmp = X ^ Y ^ Z; 196 return tmp; 197 } 198 199 private static int GG2j(int X, int Y, int Z) 200 { 201 int tmp = (X & Y) | (~X & Z); 202 return tmp; 203 } 204 205 private static int P0(int X) 206 { 207 int y = rotateLeft(X, 9); 208 y = bitCycleLeft(X, 9); 209 int z = rotateLeft(X, 17); 210 z = bitCycleLeft(X, 17); 211 int t = X ^ y ^ z; 212 return t; 213 } 214 215 private static int P1(int X) 216 { 217 int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23); 218 return t; 219 } 220 221 /** 222 * 对最后一个分组字节数据padding 223 * 224 * @param in 225 * @param bLen 226 * 分组个数 227 * @return 228 */ 229 public static byte[] padding(byte[] in, int bLen) 230 { 231 int k = 448 - (8 * in.length + 1) % 512; 232 if (k < 0) 233 { 234 k = 960 - (8 * in.length + 1) % 512; 235 } 236 k += 1; 237 byte[] padd = new byte[k / 8]; 238 padd[0] = (byte) 0x80; 239 long n = in.length * 8 + bLen * 512; 240 byte[] out = new byte[in.length + k / 8 + 64 / 8]; 241 int pos = 0; 242 System.arraycopy(in, 0, out, 0, in.length); 243 pos += in.length; 244 System.arraycopy(padd, 0, out, pos, padd.length); 245 pos += padd.length; 246 byte[] tmp = back(ConvertUtil.longToBytes(n)); 247 System.arraycopy(tmp, 0, out, pos, tmp.length); 248 return out; 249 } 250 251 /** 252 * 字节数组逆序 253 * 254 * @param in 255 * @return 256 */ 257 private static byte[] back(byte[] in) 258 { 259 byte[] out = new byte[in.length]; 260 for (int i = 0; i < out.length; i++) 261 { 262 out[i] = in[out.length - i - 1]; 263 } 264 265 return out; 266 } 267 268 public static int rotateLeft(int x, int n) 269 { 270 return (x << n) | (x >> (32 - n)); 271 } 272 273 private static int bitCycleLeft(int n, int bitLen) 274 { 275 bitLen %= 32; 276 byte[] tmp = bigEndianIntToByte(n); 277 int byteLen = bitLen / 8; 278 int len = bitLen % 8; 279 if (byteLen > 0) 280 { 281 tmp = byteCycleLeft(tmp, byteLen); 282 } 283 284 if (len > 0) 285 { 286 tmp = bitSmall8CycleLeft(tmp, len); 287 } 288 289 return bigEndianByteToInt(tmp); 290 } 291 292 private static byte[] bitSmall8CycleLeft(byte[] in, int len) 293 { 294 byte[] tmp = new byte[in.length]; 295 int t1, t2, t3; 296 for (int i = 0; i < tmp.length; i++) 297 { 298 t1 = (byte) ((in[i] & 0x000000ff) << len); 299 t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len)); 300 t3 = (byte) (t1 | t2); 301 tmp[i] = (byte) t3; 302 } 303 304 return tmp; 305 } 306 307 private static byte[] byteCycleLeft(byte[] in, int byteLen) 308 { 309 byte[] tmp = new byte[in.length]; 310 System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen); 311 System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen); 312 return tmp; 313 } 314 315// public static void main(String[] args) { 316// byte[] md = new byte[32]; 317// byte[] msg1 = "ererfeiisgod".getBytes(); 318// System.out.println(ConvertUtil.byteToHex(msg1)); 319// SM3Digest sm3 = new SM3Digest(); 320// sm3.update(msg1, 0, msg1.length); 321// sm3.doFinal(md, 0); 322// String s = new String(Hex.encode(md)); 323// System.out.println(s.toUpperCase()); 324// } 325}