【问题标题】:trouble obtaining the same hash of a file on server as on the client无法在服务器上获取与客户端上相同的文件哈希
【发布时间】:2022-11-11 05:53:44
【问题描述】:

我想获得相同的哈希上的一个文件服务器正如在客户.

我试过了:

  1. 创建要上传的表单
  2. node-forge客户端计算哈希
  3. 在 Linux 命令行上计算哈希
  4. 通过表单上传文件
  5. 将文件服务器端作为 blob 抓取
  6. 使用 .text() 服务器端读取内容
  7. 使用node-forge计算哈希服务器端

    我被困在7点。

    所以,首先我通过表单上传文件

    <form method="POST" action="?/upload" enctype="multipart/form-data">
            <input
                id="csvFile"
                name="csvFile"
                type="file"
                on:change={handleChange}
            />
        <button type="submit" class="btn">Upload</button>
    </form>
    

    我用node-forge计算浏览器中文件的哈希值:

    function handleChange(event) {
            let files = event.target.files;
            const file = files[0]
                    reader = new FileReader();
                    reader.onload = function (event) {
                    var binary = event.target.result;
                var md = forge.md.sha256.create();
                sha256 = md.update(binary).digest().toHex();
            };
                    reader.readAsBinaryString(f);
    }
    

    这计算的哈希值与我从命令行使用sha256sum 执行它时的哈希值相同,因此它是可靠的。

    但是,当我上传文件并在 SvelteKit 上处理它时,我无法获得相同的哈希值。我认为这是因为与浏览器中可用的内容相比,生成的 blob 中缺少文件名或其他内容。

    export const actions = {
        upload: async ({ request }) => {
            const formData = await request.formData()
            const file = await formData.get(`csvFile`) as File;
            const contents = await file.text()
    
            const md = forge.md.sha256.create();
            md.update(contents);
            const sha256 = md.digest().toHex()
        }
    }
    

    我不能在这里使用new FileReader(),因为我在 Node 环境中。

    如何创建完全相同的哈希服务器端和客户端?我是否需要添加文件名或其他内容以获得与命令行相同的哈希?

    提前致谢!

【问题讨论】:

    标签: node.js hash sveltekit node-forge


    【解决方案1】:

    作为文本阅读意味着一些编码。最好的方法可能是在两种情况下都将数据作为简单的数组缓冲区读取以保持一致。

    在这两种情况下,您都可以对文件使用异步 arrayBuffer() 函数。 (如果您想针对较旧的浏览器,您也可以在客户端使用FileReader.readAsArrayBuffer()。)

    在这两种情况下,您都可以将数据转换为可散列的字符串,例如通过转换单个字节并加入它们:

    const content = [...new Uint8Array(fileArrayBuffer)]
        .map(b => String.fromCharCode(b))
        .join('');
    

    【讨论】:

    • 这给了我另一个散列,但与命令行sha256sum 实用程序不同的散列。我做了`const ab = await file.arrayBuffer(); b = Buffer.from(ab);内容 = [...new Uint8Array(b)].map((b) => b.toString(16).padStart(2, '0')).join('');常量 md = forge.md.sha256.create(); md.update(内容); const sha256 = md.digest().toHex()
    • 当然,您会得到不同的哈希值。这会将数据转换为十六进制字符串,因为函数只接受字符串. Buffer.from 是多余的,顺便说一下,你已经有一个可以在Uint8Array 中使用的缓冲区。为什么要关心命令行值?重要的部分应该是客户端和服务器产生相同的哈希,你想在这里完成什么?
    • (要获得纯二进制字符串,您可能可以通过 b =&gt; String.fromCharCode(b) 映射字节;除非 JS 做了一些额外的魔法,否则应该将确切的内容作为字符串产生。如果这不起作用,您可能需要研究如何通过二进制直接到散列函数。)
    • 感谢您的最后提示。映射字节工作。
    【解决方案2】:

    SvelteKit POST 页面端点必须进行映射:

    文件 (Blob) -> ArrayBuffer -> utf8 缓冲区 -> UInt8Array -> 字符串

    async upload({ request }) {
            const formData = await request.formData();
            const blob = formData.get('csvFile');
            const ab = await blob.arrayBuffer()
            const contents = [...new Uint8Array(ab)]
                .map((b) => String.fromCharCode(b))
                .join('');
            const md = forge.md.sha256.create();
            md.update(contents);
            const sha256 = md.digest().toHex()
    

    感谢@H.B。提示。

    【讨论】:

    • Buffer.from 仍然是多余的。如果现有答案(例如我的答案)回答了整个问题,则也无需针对您的问题发布其他答案。此外,您应该接受问题的答案,似乎有几个可以接受的答案。
    猜你喜欢
    • 2013-11-19
    • 1970-01-01
    • 2021-11-20
    • 2011-07-15
    • 1970-01-01
    • 2019-01-16
    • 2019-12-18
    • 2013-11-17
    • 2017-12-29
    相关资源
    最近更新 更多