SM3算法对大文件做摘要
有個項目需要用到SM3做摘要算法,在github上找了一個實現,很多博客里用的也是這一套,先附上鏈接:SM3-JAVA實現
看文件開頭的聲明類似下面,就基本是同一套實現方案了
算法的實現是通過獲取源文件byte[],先調用一個叫padding的方法對末位填充,然后提取hash,起初因為只需要處理文本、圖片等小文件,只加了一個接收inputstream的方法,調用原算法的內容轉byte[],直到后來需要處理視頻等大文件,生產上報了內存溢出,因為算法的所有分支,最終都是獲取完整的byte[],沒辦法處理大文件
先看下原算法獲取完整byte[]后,調用padding填充:
private static byte[] padding(byte[] source) throws IOException {if (source.length >= 0x2000000000000000l) {throw new RuntimeException("src data invalid.");}long l = source.length * 8;long k = 448 - (l + 1) % 512;if (k < 0) {k = k + 512;}ByteArrayOutputStream baos = new ByteArrayOutputStream();baos.write(source);baos.write(FirstPadding);long i = k - 7;while (i > 0) {baos.write(ZeroPadding);i -= 8;}baos.write(long2bytes(l));return baos.toByteArray();}然后提取hash:
public static byte[] hash(byte[] source) throws IOException {byte[] m1 = padding(source, null);int n = m1.length / (512 / 8);byte[] b;byte[] vi = IV.toByteArray();byte[] vi1 = null;for (int i = 0; i < n; i++) {b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);vi1 = CF(vi, b);vi = vi1;}return vi1;}重點在這行:b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);
可以看到原算法獲取到完成的byte[]后,也是分64字節來處理的,可以參考這個實現,傳入inputstream,每次讀取64個字節,最后一次再調用padding做填充
參考hash(byte[])的實現,增加方法hash(InputStream):
需要注意,原來的padding算法最后寫入了完整的字節長度:baos.write(long2bytes(l));
所以這里對padding方法增加一個入參length,記錄字節數組長度,原來的調用傳null,根據參數是否為空來設置最終寫入的值:
區別主要是入參和 第四行 l 的長度計算
后來測試發現這個填充沒有的話也不影響最終生成的hash,如果最終填充的long小于實際長度的話會影響,應該是做一個校驗用的,新增的調整最好不影響原算法的處理邏輯
總結
以上是生活随笔為你收集整理的SM3算法对大文件做摘要的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux C/C++UDP通信实现
- 下一篇: node2vec的一些理解