001package top.cenze.utils.crypt; 002 003import top.cenze.utils.crypt.sm.sm3.SM3; 004 005/** 006 * SM3国密加密解密工具 007 * 008 * @author chengze 009 * @date 2023-11-14 22:36 010 */ 011public class SM3Util { 012 013 /** SM3值的长度 */ 014 private static final int BYTE_LENGTH = 32; 015 016 /** SM3分组长度 */ 017 private static final int BLOCK_LENGTH = 64; 018 019 /** 缓冲区长度 */ 020 private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1; 021 022 /** 缓冲区 */ 023 private byte[] xBuf = new byte[BUFFER_LENGTH]; 024 025 /** 缓冲区偏移量 */ 026 private int xBufOff; 027 028 /** 初始向量 */ 029 private byte[] V = SM3.iv.clone(); 030 031 private int cntBlock = 0; 032 033 public SM3Util() { 034 } 035 036 public SM3Util(SM3Util t) 037 { 038 System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length); 039 this.xBufOff = t.xBufOff; 040 System.arraycopy(t.V, 0, this.V, 0, t.V.length); 041 } 042 043 /** 044 * SM3结果输出 045 * 046 * @param out 保存SM3结构的缓冲区 047 * @param outOff 缓冲区偏移量 048 * @return 049 */ 050 public int doFinal(byte[] out, int outOff) 051 { 052 byte[] tmp = doFinal(); 053 System.arraycopy(tmp, 0, out, 0, tmp.length); 054 return BYTE_LENGTH; 055 } 056 057 public void reset() 058 { 059 xBufOff = 0; 060 cntBlock = 0; 061 V = SM3.iv.clone(); 062 } 063 064 /** 065 * 明文输入 066 * 067 * @param in 068 * 明文输入缓冲区 069 * @param inOff 070 * 缓冲区偏移量 071 * @param len 072 * 明文长度 073 */ 074 public void update(byte[] in, int inOff, int len) 075 { 076 int partLen = BUFFER_LENGTH - xBufOff; 077 int inputLen = len; 078 int dPos = inOff; 079 if (partLen < inputLen) 080 { 081 System.arraycopy(in, dPos, xBuf, xBufOff, partLen); 082 inputLen -= partLen; 083 dPos += partLen; 084 doUpdate(); 085 while (inputLen > BUFFER_LENGTH) 086 { 087 System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH); 088 inputLen -= BUFFER_LENGTH; 089 dPos += BUFFER_LENGTH; 090 doUpdate(); 091 } 092 } 093 094 System.arraycopy(in, dPos, xBuf, xBufOff, inputLen); 095 xBufOff += inputLen; 096 } 097 098 private void doUpdate() 099 { 100 byte[] B = new byte[BLOCK_LENGTH]; 101 for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH) 102 { 103 System.arraycopy(xBuf, i, B, 0, B.length); 104 doHash(B); 105 } 106 xBufOff = 0; 107 } 108 109 private void doHash(byte[] B) 110 { 111 byte[] tmp = SM3.CF(V, B); 112 System.arraycopy(tmp, 0, V, 0, V.length); 113 cntBlock++; 114 } 115 116 private byte[] doFinal() 117 { 118 byte[] B = new byte[BLOCK_LENGTH]; 119 byte[] buffer = new byte[xBufOff]; 120 System.arraycopy(xBuf, 0, buffer, 0, buffer.length); 121 byte[] tmp = SM3.padding(buffer, cntBlock); 122 for (int i = 0; i < tmp.length; i += BLOCK_LENGTH) 123 { 124 System.arraycopy(tmp, i, B, 0, B.length); 125 doHash(B); 126 } 127 return V; 128 } 129 130 public void update(byte in) 131 { 132 byte[] buffer = new byte[] { in }; 133 update(buffer, 0, 1); 134 } 135 136 public int getDigestSize() 137 { 138 return BYTE_LENGTH; 139 } 140 141// public static void main(String[] args) 142// { 143// byte[] md = new byte[32]; 144// byte[] msg1 = "ererfeiisgod".getBytes(); 145// SM3Digest sm3 = new SM3Digest(); 146// sm3.update(msg1, 0, msg1.length); 147// sm3.doFinal(md, 0); 148// String s = new String(Hex.encode(md)); 149// System.out.println(s.toUpperCase()); 150// } 151}