import {
// createAdler32(): Promise<IHasher>
// createBLAKE2b(bits?: number, key?: IDataType): Promise<IHasher> // default is 512 bits
// createBLAKE2s(bits?: number, key?: IDataType): Promise<IHasher> // default is 256 bits
// createBLAKE3(bits?: number, key?: IDataType): Promise<IHasher> // default is 256 bits
// createCRC32(polynomial?: number): Promise<IHasher> // default polynomial is 0xedb88320, for CRC32C use 0x82f63b78
// createCRC64(polynomial?: number): Promise<IHasher> // default polynomial is 'c96c5795d7870f42' (ECMA)
// createKeccak(bits?: 224 | 256 | 384 | 512): Promise<IHasher> // default is 512 bits
// createMD4(): Promise<IHasher>
createMD5, //createMD5(): Promise<IHasher>
// createRIPEMD160(): Promise<IHasher>
createSHA1, //createSHA1(): Promise<IHasher>
// createSHA224(): Promise<IHasher>
createSHA256, //createSHA256(): Promise<IHasher>
createSHA384, //// createSHA384(): Promise<IHasher>
createSHA512 //createSHA512(): Promise<IHasher>
// createSHA3(bits?: 224 | 256 | 384 | 512): Promise<IHasher> // default is 512 bits
// createSM3(): Promise<IHasher>
// createWhirlpool(): Promise<IHasher>
// createXXHash32(seed: number): Promise<IHasher>
// createXXHash64(seedLow: number, seedHigh: number): Promise<IHasher>
// createXXHash3(seedLow: number, seedHigh: number): Promise<IHasher>
// createXXHash128(seedLow: number, seedHigh: number): Promise<IHasher>
// createHMAC(hashFunction: Promise<IHasher>, key: IDataType): Promise<IHasher>
} from 'hash-wasm'
import get from 'lodash-es/get.js'
import isestr from './isestr.mjs'
import isnum from './isnum.mjs'
import isblob from './isblob.mjs'
import isfile from './isfile.mjs'
import haskey from './haskey.mjs'
import cdbl from './cdbl.mjs'
/**
* 計算檔案HASH值
*
* 瀏覽器端輸入檔案Blob或File,可支援大檔
*
* 因Node.js亦已支援Blob,可用new Blob([fs.readFileSync(fp)])取得Blob做為輸入
*
* Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/getFileHash.test.mjs Github}
* @memberOf wsemi
* @param {Blob|File} inp 輸入檔案Blob或File
* @param {Object} [opt={}] 輸入設定物件,預設{}
* @param {String} [opt.type='sha512'] 輸入計算HASH方法,預設'sha512'
* @returns {Promise} 回傳Promise,此時若成功則resolve代表檔案HASH值,若失敗則reject錯誤訊息
* @example
*
* let test = async () => {
*
* let ms = []
*
* let fdt = './_test_getFileBasicHash'
* fsCreateFolder(fdt) //創建臨時任務資料夾
*
* let fn = 't1.txt'
* let fp = `${fdt}/abc/${fn}`
*
* fsWriteText(fp, 'xyz')
*
* let ab = fs.readFileSync(fp)
* let bb = new Blob([ab])
*
* let h1 = await getFileBasicHash(bb)
* console.log('getFileBasicHash(sha512)', h1)
* ms.push({ 'getFileBasicHash(sha512)': h1 })
*
* let h2 = await getFileBasicHash(bb, { type: 'sha256' })
* console.log('getFileBasicHash(sha256)', h2)
* ms.push({ 'getFileBasicHash(sha256)': h2 })
*
* fsDeleteFolder(fdt) //刪除臨時任務資料夾
*
* console.log('ms', ms)
* return ms
* }
* await test()
* .catch((err) => {
* console.log(err)
* })
* // getFileBasicHash(sha512) 4a3ed8147e37876adc8f76328e5abcc1b470e6acfc18efea0135f983604953a58e183c1a6086e91ba3e821d926f5fdeb37761c7ca0328a963f5e92870675b728
* // getFileBasicHash(sha256) 3608bca1e44ea6c4d268eb6db02260269892c0b42b86bbf1e77a6fa16c3c9282
* // ms [
* // {
* // 'getFileBasicHash(sha512)': '4a3ed8147e37876adc8f76328e5abcc1b470e6acfc18efea0135f983604953a58e183c1a6086e91ba3e821d926f5fdeb37761c7ca0328a963f5e92870675b728'
* // },
* // {
* // 'getFileBasicHash(sha256)': '3608bca1e44ea6c4d268eb6db02260269892c0b42b86bbf1e77a6fa16c3c9282'
* // }
* // ]
*
*/
async function getFileBasicHash(inp, opt = {}) {
//瀏覽器crypto.subtle.digest是只支援一次性記憶體計算, 又只能非同步async計算, 故採用hash-wasm計算可支援超大檔
//check
if (!isblob(inp) && !isfile(inp)) {
console.log('inp', inp)
return Promise.reject(`inp is not a Blob or File`)
}
//type
let type = get(opt, 'type', '')
if (!isestr(type)) {
type = 'sha512'
}
//chunkSize
let chunkSize = get(opt, 'chunkSize')
if (!isnum(chunkSize)) {
chunkSize = 64 * 1024 * 1024 //64mb
}
chunkSize = cdbl(chunkSize)
//kp
let kp = {
'MD5': createMD5,
'SHA-1': createSHA1,
'SHA-256': createSHA256,
'SHA-384': createSHA384,
'SHA-512': createSHA512,
'md5': createMD5,
'sha1': createSHA1,
'sha256': createSHA256,
'sha384': createSHA384,
'sha512': createSHA512,
}
// createMD5, //createMD5(): Promise<IHasher>
// createSHA1, //createSHA1(): Promise<IHasher>
// createSHA256, //createSHA256(): Promise<IHasher>
// createSHA512, //createSHA512(): Promise<IHasher>
// createSHA3 //createSHA3(bits?: 224 | 256 | 384 | 512): Promise<IHasher> // default is 512 bits
//check
if (!haskey(kp, type)) {
return Promise.reject(`type[${type}] must be one of [ 'md5', 'sha1', 'sha256', 'sha384', 'sha512' ]`)
}
//funCreate
let funCreate = get(kp, type)
//hasher
let hasher = await funCreate()
//calc hash
let offset = 0
while (offset < inp.size) {
let chunk = inp.slice(offset, offset + chunkSize)
let buffer = await chunk.arrayBuffer()
hasher.update(new Uint8Array(buffer))
offset += chunkSize
}
let hashHex = hasher.digest()
return hashHex
}
export default getFileBasicHash