日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

SM3算法对大文件做摘要

發(fā)布時(shí)間:2023/12/31 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SM3算法对大文件做摘要 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

有個(gè)項(xiàng)目需要用到SM3做摘要算法,在github上找了一個(gè)實(shí)現(xiàn),很多博客里用的也是這一套,先附上鏈接:SM3-JAVA實(shí)現(xiàn)

看文件開(kāi)頭的聲明類(lèi)似下面,就基本是同一套實(shí)現(xiàn)方案了

算法的實(shí)現(xiàn)是通過(guò)獲取源文件byte[],先調(diào)用一個(gè)叫padding的方法對(duì)末位填充,然后提取hash,起初因?yàn)橹恍枰幚砦谋尽D片等小文件,只加了一個(gè)接收inputstream的方法,調(diào)用原算法的內(nèi)容轉(zhuǎn)byte[],直到后來(lái)需要處理視頻等大文件,生產(chǎn)上報(bào)了內(nèi)存溢出,因?yàn)樗惴ǖ乃蟹种?#xff0c;最終都是獲取完整的byte[],沒(méi)辦法處理大文件

先看下原算法獲取完整byte[]后,調(diào)用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;}

重點(diǎn)在這行:b = Arrays.copyOfRange(m1, i * 64, (i + 1) * 64);
可以看到原算法獲取到完成的byte[]后,也是分64字節(jié)來(lái)處理的,可以參考這個(gè)實(shí)現(xiàn),傳入inputstream,每次讀取64個(gè)字節(jié),最后一次再調(diào)用padding做填充
參考hash(byte[])的實(shí)現(xiàn),增加方法hash(InputStream):

private static byte[] hash(InputStream inputStream) throws IOException {byte[] vi = IV.toByteArray();byte[] vi1 = null;byte[] bytes = new byte[64];int length = -1;int totalLength = 0;while ((length = inputStream.read(bytes)) != -1) {totalLength += length;if (inputStream.available() == 0) {bytes = padding(Arrays.copyOfRange(bytes, 0, length), totalLength);//=========================補(bǔ)充更正=========================//如果padding后長(zhǎng)度 > 64,分兩次處理,感謝評(píng)論區(qū)朋友的提醒if (bytes.length > 64) {for (int i = 0; i <= 1; i++) {byte[] b = Arrays.copyOfRange(bytes, i * 64, (i + 1) * 64);vi1 = CF(vi, b);vi = vi1;}break;}//=========================補(bǔ)充更正=========================}vi1 = CF(vi, bytes);vi = vi1;}return vi1;}

需要注意,原來(lái)的padding算法最后寫(xiě)入了完整的字節(jié)長(zhǎng)度:baos.write(long2bytes(l));
所以這里對(duì)padding方法增加一個(gè)入?yún)ength,記錄字節(jié)數(shù)組長(zhǎng)度,原來(lái)的調(diào)用傳null,根據(jù)參數(shù)是否為空來(lái)設(shè)置最終寫(xiě)入的值:

private static byte[] padding(byte[] source, Integer length) throws IOException {if (source.length >= 0x2000000000000000l) {throw new RuntimeException("src data invalid.");}long l = length == null ? source.length * 8 : 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();}

區(qū)別主要是入?yún)⒑?第四行 l 的長(zhǎng)度計(jì)算

后來(lái)測(cè)試發(fā)現(xiàn)這個(gè)填充沒(méi)有的話(huà)也不影響最終生成的hash,如果最終填充的long小于實(shí)際長(zhǎng)度的話(huà)會(huì)影響,應(yīng)該是做一個(gè)校驗(yàn)用的,新增的調(diào)整最好不影響原算法的處理邏輯

總結(jié)

以上是生活随笔為你收集整理的SM3算法对大文件做摘要的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。