JavaScript计算文件Hash值(sha1 sha 256 md5)

一、引入外部库CryptoJS(简单)

1、字符串Hash

<!DOCTYPE html>
<html>
<head>
    <title>Hash算法</title>
    <script type="text/javascript" src="CryptoJS-3.1.2/rollups/md5.js"></script>
    <script type="text/javascript" src="CryptoJS-3.1.2/rollups/sha1.js"></script>
    <script type="text/javascript" src="CryptoJS-3.1.2/rollups/sha256.js"></script>
    <script type="text/javascript" src="CryptoJS-3.1.2/rollups/hmac-sha1.js"></script>
    <script type="text/javascript" src="CryptoJS-3.1.2/rollups/hmac-sha256.js"></script>
</head>
<body>
<script type="text/javascript">
    // ======================== Hash算法 ========================
    console.log('MD5:', CryptoJS.MD5("abc").toString());
    console.log('SHA1:', CryptoJS.SHA1("abc").toString());
    console.log('SHA256:', CryptoJS.SHA256("abc").toString());

    console.log('hmac-sha1:', CryptoJS.HmacSHA1("abc", "123").toString());
    console.log('hmac-sha256:', CryptoJS.HmacSHA256("abc", "123").toString());
</script>
</body>
</html>

2、文件Hash

<!DOCTYPE html>
<html>
<head>
    <title>Hash算法</title>
    <script type="text/javascript" src="CryptoJS-3.1.2/rollups/md5.js"></script>
</head>
<body>
<script type="text/javascript">
    window.onload = function () {
        function fileMd5Sum(file) {
            const fileReader = new FileReader();
            fileReader.onloadend = (ev) => {
                const md5 = CryptoJS.MD5(CryptoJS.enc.Latin1.parse(ev.target.result)).toString(CryptoJS.enc.Hex);
                console.log(md5);
            }
            fileReader.readAsBinaryString(file);
        }

        // 获取文件
        let file = document.getElementById("file");
        file.addEventListener("change", function () {
            fileMd5Sum(file.files[0]);
        })
    }
</script>
<input type="file" id="file"/>
</body>
</html>

3、参考

CryptoJS常用的加密算法使用及原理

https://blog.csdn.net/qq_21531681/article/details/108608131

二、不引入外部库(复杂)

【注意】要求https访问才可以使用。

1、字符串Hash

const content2 = '这是用来计算SHA-256的字符串的方法';
 
async function digestMessage(message) {
  const msgUint8 = new TextEncoder().encode(message);                           // encode as (utf-8) Uint8Array
  const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);           // hash the message
  const hashArray = Array.from(new Uint8Array(hashBuffer));                     // convert buffer to byte array
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string
  return hashHex;
}
 
digestMessage(content2)
  .then(digestHex => console.log(digestHex));

参考:
vue/js通过计算 字符串 / 文件 sha1(SHA-1)值、sha256值等方法
https://blog.csdn.net/weixin_42634991/article/details/124601829

2、文件Hash

三种方法计算Hash值的方法都是相同的;只是将Hash值转换为16进制base 64不同。

(1)方法一

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script type="text/javascript">
        window.onload = function () {
            let file = document.getElementById("fileid");
            file.addEventListener("change", function () {
                let read = new FileReader();
                read.readAsArrayBuffer(file.files[0])
                read.onload = function () {
                    (async function () {
    					//let inputBytes = new TextEncoder().encode("hello world");
                        let sha1 = await crypto.subtle.digest('SHA-1', read.result).then(a => Array.from(new Uint8Array(a)).map(a => a.toString(16).padStart(2, '0')).join(""));
                        console.log(sha1);
                    })();
                }
            })
        }
    </script>
</head>
<body>
<input type="file" id="fileid">
</body>
</html>

参考:

不用引入外部库,在浏览器上一行计算出SHA-1/SHA-256的结果

https://blog.csdn.net/emu/article/details/121862519

(2)方法二

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script type="text/javascript">
        window.onload = function () {
            /**
             * 获取16进制摘要字符串
             * @param buffer
             * @returns {string}
             */
            function hex(buffer) {
                let code = [];
                let view = new DataView(buffer);
                for (var i = 0; i < view.byteLength; i += 4) {
                    value = view.getUint32(i)
                    let stringValue = value.toString(16)
                    // 填充切片
                    let padding = '00000000'
                    let paddedValue = (padding + stringValue).slice(-padding.length)
                    code.push(paddedValue);
                }
                return code.join("");
            }

            /**
             * 获取文件,计算hash
             * @type {HTMLElement}
             */
            let file = document.getElementById("fileid");
            file.addEventListener("change", function () {
                let read = new FileReader();
                read.readAsArrayBuffer(file.files[0])
                read.onload = function () {
                    (async function () {
                        let arr = await crypto.subtle.digest('SHA-256', read.result);
                        //console.log(arr);
                        //调用函数,获取16进制摘要字符串
                        let sha256Msg = hex(arr);
                        console.log(sha256Msg);
                    })();

                }
            })
        }
    </script>
</head>
<body>
<input type="file" id="fileid">
</body>
</html>

参考:

javascript获取文件sha-256,sha-384,sha-512摘要,验证文件是否被篡改,验证文件一致性,文件安全管理,计算文件的MD5值

https://blog.csdn.net/qq_41974199/article/details/124232425

(3)方法三

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script type="text/javascript">
        window.onload = function () {

            // from: https://stackoverflow.com/a/40031979/9014097
            function buf2hex(buffer) { // buffer is an ArrayBuffer
                return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
            }

            // from https://stackoverflow.com/a/11562550/9014097
            function buf2Base64(buffer) {
                return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)));
            }

            /**
             * 获取文件,计算hash
             * @type {HTMLElement}
             */
            let file = document.getElementById("fileid");
            file.addEventListener("change", function () {
                let read = new FileReader();
                read.readAsArrayBuffer(file.files[0])
                read.onload = function () {
                    (async function () {
                        let hashBytes = await window.crypto.subtle.digest("SHA-256", read.result);
                        console.log(JSON.stringify({hash: buf2hex(hashBytes)})); // {"hash":"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"}
                        console.log(JSON.stringify({hash: buf2Base64(hashBytes)})); // {"hash":"16j7swfXgJRpypq8sAguT41WUeRtPNt2LQLQvzfJ5ZI="}
                    })();

                }
            })
        }
    </script>
</head>
<body>
<input type="file" id="fileid">
</body>
</html>

3、参考资料

为什么crypto.subtle.digest返回一个空对象

https://cloud.tencent.com/developer/ask/sof/767149

好的,我可以为您提供一个 TypeScript 的代码示例,使用 Web Workers 来实现大文件分片计算 SHA256MD5SHA1SHA512 哈希: ```typescript // 定义一个工作线程的类型,包含计算函数和计算类型 type WorkerType = { compute: (data: ArrayBuffer) => Promise<string>; type: string; }; // 定义一个函数,将文件分成多个 ArrayBuffer function splitFile(file: File, chunkSize: number): Promise<ArrayBuffer[]> { return new Promise((resolve, reject) => { const fileSize = file.size; const chunks = []; let offset = 0; const reader = new FileReader(); function readSlice() { if (offset >= fileSize) { resolve(chunks); return; } const slice = file.slice(offset, offset + chunkSize); reader.readAsArrayBuffer(slice); offset += chunkSize; } reader.addEventListener("load", () => { chunks.push(reader.result); readSlice(); }); reader.addEventListener("error", () => { reject(reader.error); }); readSlice(); }); } // 定义一个函数,创建一个工作线程,用于计算哈希 function createWorker(worker: WorkerType): Worker { const workerURL = URL.createObjectURL( new Blob([`(${worker.compute})()`], { type: "application/javascript" }) ); const hashWorker = new Worker(workerURL); return hashWorker; } // 定义一个函数,使用 Web Workers 并行计算文件的哈希 function computeHashes(file: File): Promise<{ [key: string]: string }> { const chunkSize = 1024 * 1024; // 分片大小为 1MB const workers = [ { compute: sha256, type: "SHA-256" }, { compute: md5, type: "MD5" }, { compute: sha1, type: "SHA-1" }, { compute: sha512, type: "SHA-512" }, ]; const promises = workers.map((worker) => { const hashWorker = createWorker(worker); const chunksPromise = splitFile(file, chunkSize); return chunksPromise.then((chunks) => { const hashPromises = chunks.map((chunk) => { return new Promise<string>((resolve) => { const message = { data: chunk }; const onMessage = (event: MessageEvent) => { hashWorker.removeEventListener("message", onMessage); resolve(event.data); }; hashWorker.addEventListener("message", onMessage); hashWorker.postMessage(message, [message.data]); }); }); return Promise.all(hashPromises).then((hashes) => ({ [worker.type]: hashes.join(""), })); }); }); return Promise.all(promises).then((results) => { const hashes = Object.assign({}, ...results); return hashes; }); } // SHA-256 计算函数 function sha256(): void { self.addEventListener("message", async (event: MessageEvent) => { const data = event.data as ArrayBuffer; const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); self.postMessage(hashHex); }); } // MD5 计算函数 function md5(): void { self.addEventListener("message", async (event: MessageEvent) => { const data = event.data as ArrayBuffer; const hashBuffer = await crypto.subtle.digest("MD5", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); self.postMessage(hashHex); }); } // SHA-1 计算函数 function sha1(): void { self.addEventListener("message", async (event: MessageEvent) => { const data = event.data as ArrayBuffer; const hashBuffer = await crypto.subtle.digest("SHA-1", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); self.postMessage(hashHex); }); } // SHA-512 计算函数 function sha512(): void { self.addEventListener("message", async (event: MessageEvent) => { const data = event.data as ArrayBuffer; const hashBuffer = await crypto.subtle.digest("SHA-512", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); self.postMessage(hashHex); }); } ``` 使用方法: ```typescript const fileInput = document.getElementById("file-input") as HTMLInputElement; fileInput.addEventListener("change", async () => { const file = fileInput.files[0]; const hashes = await computeHashes(file); console.log(hashes); }); ``` 该示例使用 Web Workers 并行计算文件SHA256MD5SHA1SHA512 哈希。它将文件分成多个 ArrayBuffer,然后使用指定的算法计算每个 ArrayBuffer 的哈希。最后,它将所有哈希组合成一个包含 SHA256MD5SHA1SHA512 哈希的对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值