SM3算法对大文件做摘要
有個(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):
需要注意,原來(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ě)入的值:
區(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)題。
- 上一篇: Linux C/C++UDP通信实现
- 下一篇: node2vec的一些理解