14

我正在尝试创建一个与 IPFS 兼容的 mutihash,但它不匹配。我在这里问是因为我还没有找到一个从散列到最终结果的例子。

echo -n multihash > multihash.txt


ipfs add multihash.txt
added QmZLXzjiZU39eN8QirMZ2CGXjMLiuEkQriRu7a7FeSB4fg multihash.txt


sha256sum multihash.txt
9cbc07c3f991725836a3aa2a581ca2029198aa420b9d99bc0e131d9f3e2cbe47  multihash.txt

node

> var bs58=require('bs58')
bs58.encode(new Buffer('9cbc07c3f991725836a3aa2a581ca2029198aa420b9d99bc0e131d9f3e2cbe47','hex'))
'BYptxaTgpcBrqZx9tghNCWFfUuYBcGfLydEvDjXqBV7k'

> var mh=require('multihashes')
mh.toB58String(mh.encode(new Buffer('9cbc07c3f991725836a3aa2a581ca2029198aa420b9d99bc0e131d9f3e2cbe47','hex'), 'sha2-256'))
'QmYtUc4iTCbbfVSDNKvtQqrfyezPPnFvE33wFmutw9PBBk'

QmZLXzjiZU39eN8QirMZ2CGXjMLiuEkQriRu7a7FeSB4fg目的是使用 multihashes 包重新创建 IPFS 路径。

我可以创建与QmYtUc...9PBBk此处示例中所示相同的哈希: https ://github.com/multiformats/multihash#example

4

5 回答 5

14

IPFS 使用多重哈希,格式如下:

base58(<varint hash function code><varint digest size in bytes><hash function output>)

哈希函数代码列表可在此表中找到。

这是使用SHA2-256作为散列函数的过程的一些伪代码。

sha2-256   size  sha2-256("hello world")
0x12       0x20  0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

连接这三个项目将产生

1220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

然后将其编码为base58

QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4

这是一个如何在 JavaScript 中实现多哈希的示例:


    const crypto = require('crypto')
    const bs58 = require('bs58')
    
    const data = 'hello world'
    
    const hashFunction = Buffer.from('12', 'hex') // 0x20
    
    const digest = crypto.createHash('sha256').update(data).digest()
    
    console.log(digest.toString('hex')) // b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
    
    const digestSize = Buffer.from(digest.byteLength.toString(16), 'hex')
    
    console.log(digestSize.toString('hex')) // 20
    
    const combined = Buffer.concat([hashFunction, digestSize, digest])
    
    console.log(combined.toString('hex')) // 1220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
    
    const multihash = bs58.encode(combined)
    
    console.log(multihash.toString()) // QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4

有一个 CLI 可用于生成多重哈希:

    $ go get github.com/multiformats/go-multihash/multihash
    $ echo -n "hello world" | multihash -a sha2-256
    QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4

正如@David 所说,IPFS 中的文件被“转换”为 Unixfs“文件”,它是DAG中文件的表示。因此,当您使用add将文件上传到 IPFS 时,数据具有元数据包装器,当您对其进行多重哈希处理时,它会给您带来不同的结果。

例如:

    $ echo -n "hello world" | ipfs add -Q
    Qmf412jQZiuVUtdgnB36FXFX7xg5V6KEbSJ4dpQuhkLyfD

这是 Node.js 中的一个示例,说明如何生成与以下内容完全相同的多重哈希ipfs add

    const Unixfs = require('ipfs-unixfs')
    const {DAGNode} = require('ipld-dag-pb')
    
    const data = Buffer.from('hello world', 'ascii')
    const unixFs = new Unixfs('file', data)
    
    DAGNode.create(unixFs.marshal(), (err, dagNode) => {
      if (err) return console.error(err)
    
      console.log(dagNode.toJSON().multihash) // Qmf412jQZiuVUtdgnB36FXFX7xg5V6KEbSJ4dpQuhkLyfD
    })
于 2018-07-12T11:42:28.977 回答
2

IPFS 中的文件被“转换”为 Unixfs 文件,这是 DAG 中文件的表示形式,在您的示例中,您使用 sha2-256 直接对 multihash.txt 进行散列,但 IPFS 内部发生的是:

于 2016-12-06T16:14:38.290 回答
1

其他一些答案已经过时了。这对我有用:

const { UnixFS } = require('ipfs-unixfs') // @4.0.3
const { DAGNode } = require('ipld-dag-pb') // @0.22.2

const data = Buffer.from("Hello World\n")
const file = new UnixFS({data})
const node = new DAGNode(file.marshal())

const link = await node.toDAGLink()
const cid = link.Hash
console.log(cid.toV0().toString())
// Qmf412jQZiuVUtdgnB36FXFX7xg5V6KEbSJ4dpQuhkLyfD
于 2019-09-21T00:29:19.470 回答
0

目前最简单的方法是简单地使用ipfs-http-client. 此线程中的所有上述解决方案不再对我有用。

import ipfsClient from "ipfs-http-client";
const ipfs = ipfsClient(IPFS_PROVIDER, "5001", { protocol: "https" });

// onlyHash: true only generates the hash and doesn't upload the file
const hash = (await ipfs.add(new Buffer(vuln), { onlyHash: true }))[0].hash
于 2019-03-25T13:54:36.567 回答
0
const { randomBytes } = require('crypto')
const multihash = require('multihashes')

const buffer = Buffer.from(randomBytes(32), 'hex')
const encoded = multihash.encode(buffer, 'sha2-256')
const hash = multihash.toB58String(encoded)
console.log(hash)
于 2019-01-04T17:51:25.130 回答