区块链 | IPFS:CID

🦊原文:Anatomy of a CID
🦊写在前面:本文属于搬运博客,自己留存学习。



1 CID

在分布式网络中与其他节点交换数据时,我们依赖于内容寻址(而不是中心化网络的位置寻址)来安全地定位和识别数据。

CID 规范起源于 IPFS,现在以 Multiformats 形式存在,并支持包括 IPFS、IPLD、libp2p 和 Filecoin 在内的系统。尽管我们在教程中会分享一些 IPFS 的例子,但本教程实际上是关于 CID 自身的结构,它作为这些分布式信息系统的核心标识符,用于引用内容。

内容标识符(CID)是一种自描述的内容寻址标识符。

自描述是指,标识符能够自行表达其含义或者数据类型。例如 HTTP 中的 URL就是一个自描述的标识符,因为它包含了指向资源的信息(如文件路径),并且基于协议和结构,用户和系统可以理解其含义。

CID 不指示内容存储的位置,而是基于内容本身形成一种地址。CID 的长度取决于内容的哈希,而不是内容本身的大小。由于在 IPFS 中大多数内容都使用 sha2-256 进行哈希处理,因此大多数 CID 都具有相同的大小,即 256 位或称 32 字节。

例如,如果我们在 IPFS 网络中存储 土豚 的图像,它的 CID 将如下所示:

QmcRD4wkPPi6dig81r5sLj9Zm1gDCL4zgpEj9CfuRrGbzF

访问方式:https://ipfs.io/ipfs/QmcRD4wkPPi6dig81r5sLj9Zm1gDCL4zgpEj9CfuRrGbzF

创建 CID 的第一步是使用 加密算法 转换输入的数据。具体来说,是将任意大小的输入映射到固定大小的输出。如下图所示:

在这里插入图片描述
这种转换称为 加密哈希摘要(cryptographic hash digest)或简称为 哈希

个人理解:不管是文本、图片还是视频,它们在计算机中都是以二进制的形式进行存储的,即一个 01 字符串。而哈希函数要做的事,就是将不同文件不同长度的 01 字符串转换为固定长度的 01 字符串。

使用的 加密算法 必须生成具有以下特征的哈希:

  • 确定性:对于任何给定的输入数据,加密算法必须始终产生相同的输出哈希,确保一致性。
  • 抗碰撞性:即使输入数据发生微小变化,也应导致完全不同的哈希值,以保证数据的唯一性。
  • 不可逆性:从哈希值应当无法反推出原始数据,确保数据的隐私和安全。
  • 唯一标识:每份文件都应该有一个独特的哈希值,确保数据的不可篡改性和可追溯性。

当我们使用内容地址去获取数据时,我们可以保证看到数据的预期版本。这与中心化网络上的位置寻址有很大的不同,在中心化网络中,给定地址(URL)处的内容可能会随时间变化。

说明:在去中心化网络中,我们使用 CID 去获取数据;在中心化网络中,我们使用 URL 去获取数据。

哈希并不是 IPFS 所独有的,还有许多其他的哈希算法,如 sha2-256、blake2b、sha3-256 和 sha3-512,以及不再安全的 sha1 和 md5 等。IPFS 默认使用 sha2-256,尽管 CID 支持几乎任何强大的加密哈希算法。



2 CIDv0

随着时间的推移,某些哈希算法可能被证明对于 IPFS 和其他分布式信息系统的内容寻址是不够安全的。

因此,我们的系统需要支持多种加密算法,同时我们应该能够知道是哪种算法被用来生成特定内容的哈希值。为了支持多种哈希算法,我们使用了多重哈希。



2.1 多重哈希

多重哈希(multihash)是一种自描述的哈希,它本身包含元数据,这些元数据描述了其长度以及生成它的加密算法。

多重哈希遵循 TLV 模式,即 type — length — value。也就是说,原始哈希 value 前面附带着所使用的哈希算法的类型 type 和哈希的长度 length。如下图所示:

在这里插入图片描述

  • type:用于生成哈希的加密算法的标识符。例如,sha2-256 的标识符是 18,即十六进制的 12;
  • length:哈希的实际长度。使用 sha2-256 时,它将是 256 位,相当于 32 字节;
  • value:实际的哈希值;

通过查看 multicodec 表,可以获取各个哈希算法对应的标识符。



2.2 基数编码

为了将 CID 表示为紧凑的字符串而不是纯二进制(一串 0 和 1),我们可以使用基数编码(base encoding)。

在 IPFS 最初创建时,它使用 base58btc 编码来生成看起来像这样的 CID:

QmY7Yh4UquoXHLPFo2XbhXkhBvFoPwmQUSa92pxnxjQuPU

多重哈希和 base58btc 编码构成了第一版 CID,即如今所说的版本 CIDv0,以 Qm 开头的序列仍然是它的一个显著特征。

然而,随着时间的推移,人们开始对多重哈希是否足够的问题产生了疑问:

  • 我们如何知道使用了什么方法来编码数据?
  • 我们如何知道使用了什么方法来创建 CID 的字符串表示?我们是否会一直使用 base58btc

为了应对这些担忧,有必要对 CID 的下一版本进行改进。

个人理解:在本文中,“基数编码” 是指将二进制转换为可读的字符串,“编码” 是指将文件转换为二进制。



3 CIDv1

CIDv0 使用多重哈希来支持多种哈希函数。这允许我们针对特定内容创建哈希值,且可以选择不同的哈希算法进行处理。有了这一机制,我们日后便能通过这些哈希值来辨识内容。



3.1 多码前缀

但当我们试图阅读数据本身时,如何知道采用了哪种编码方式?数据可能是由 CBOR、Protobuf 或纯 JSON 等编码的。为了解决这个问题,CIDv1 引入了另一个前缀,用以唯一标识所使用的编码方法。

个人理解:哈希是将任意长度的 01 字符串转换为固定长度的 01 字符串,而编码是将非 01 字符串的数据本身转换为 01 字符串。

多码前缀(multicodec prefix)指示了数据使用了哪种编码方式。如下图所示:

在这里插入图片描述

多码支持许多不同类型的编码,每种编码都有自己的简短码缀,可以在 complete 表中查看。

在上述示例中,我们了解到使用 dag-pb 编码的数据是如何被表示在 CID 中的。其中,dag-pb 是众多 IPLD 编码格式中的一种。由于 IPFS 总是选择一种 IPLD 格式来处理其数据,因此 IPFS 生成的 CID 中的多码前缀必然对应于一个 IPLD 编码。

IPLD 是指 Inter Planetary Linked Data,星际链接数据

需要指出的是,多码不仅仅是为了 IPFS 和 IPLD 而设计的,它还是 Multiformats 项目的一部分。这个项目最初是从 IPFS 分离出来的,现在它支持包括我们正在学习的 CID 规范在内的许多其他项目和协议。



3.2 版本前缀

添加多码前缀后,CIDv1 包含以下字段:

<multicodec><multihash-algorithm><multihash-length><multihash-hash>

那么我们如何区分不同版本的 CID 呢?答:版本前缀。如下图所示:

在这里插入图片描述

现在我们的 CID 看起来像这样:

<cid-version><multicodec><multihash>

其中,<cid-version> 代表 CID 的版本是 0 还是 1 。

注意:<multihash> 包含了 <multihash-algorithm><multihash-length><multihash-hash>。特别地,只有 CIDv1 具有 <cid-version>,而 CIDv0 只有 <multihash>



3.3 多基前缀

CIDv1 以二进制的形式为我们提供了以下信息:

<cid-version><multicodec><multihash>

由于二进制 CID 对人类不太友好,因此我们可以将这些二进制 CID 表示为字符串形式,即把二进制数据表示为字符串。

采用的就是前文提到的基数编码技术。

示例:

bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

在二进制和字符串形式之间转换数据需要进行基数编码,因此在处理字符串格式的 CID 时,我们需要知道应用于二进制数据的基数编码的类型。

在 CIDv0 中,哈希总是使用 base58btc 进行编码。因此我们可以直接假设 CIDv0 哈希是由 base58btc 编码的。然而,由于环境限制(例如 DNS 名称),我们需要支持其他基数编码的能力。你猜对了,我们可以添加另一个前缀!

多基数前缀(multibase prefix),用于表示 CID 在进行格式转换时使用的基数编码,仅用于 CID 的字符串形式:

Binary:
<cid-version><multicodec><multihash>
String:
<base>base(<cid-version><multicodec><multihash>)

其中,base( ) 应该是指使用某种基数编码方法,对括号中的内容进行基数编码。

让我们来分析两个 CID 的字符串形式示例:

CIDv0:
QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR
CIDv1:
bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

易知第一个 CID 是一个 CIDv0,因为它以 Qm 开头。所有以 Qm 开头的哈希,都可以解释为采用的是 base58btc 基数编码。第二个示例以 b 开头,这是 base32 的基数编码前缀标识符,大多数 IPFS 实现默认使用 base32



4 One hash, multiple CID versions

我们可以将任何的 IPFS CID 粘贴到 CID Inspector 中,以可视化其所有前缀及其代表的内容。



4.1 示例 1:CIDv1

bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

通过 CID Inspector 工具查看结果:

在这里插入图片描述

我这里只截取了一部分,请自行查看剩余部分。

我们可以看到工具为我们解析了许多部分:

  • 人类可读 CID:将 CID 的每个部分分解为人类可以轻松阅读的形式;
  • 多基数:基数的标识符,在这个例子中是 b,代表 base32
  • 多编码:编码的标识符,在这个例子中是 0x70,代表 dag-pb,一种 IPLD 格式;
  • 多哈希:将多哈希分解为所使用的哈希算法、哈希的长度、内容哈希本身。

其中,18 是哈希算法 sha2-256 的代码,哈希的长度是 256 位即 32 字节,内容哈希本身是十六进制的摘要。

从 “人类可读 CID” 中,我们可以看到在添加 CIDv1 的前缀之前,内容的原始哈希是:

C3C4733EC8AFFD06CF9E9FF50FFC6BCD2EC85A6170004BB709669C31DE94391A


4.2 示例 2:CIDv0

QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR

通过 CID Inspector 工具查看结果:

在这里插入图片描述

在 CIDv0 的结果中,多基数和多编码都显示为 “implicit”。这是由于 CIDv0 没有这两个前缀,因此它们被分别默认为 base58btcdag-pb

在原文的截图中,两个前缀都显示的是 “implicit”,但是我查看到的多编码并不是 “implicit”。

在 CIDV1(Base32) 标签下,我们看到:

bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi

这与第一个示例中的 CID 完全相同!CID 检查器为我们提供了从 CIDv0 到 CIDv1 的转换。

注意,CIDv0 示例与 CIDv1 示例中的 “人类可读 CID” 的末尾完全相同:

C3C4733EC8AFFD06CF9E9FF50FFC6BCD2EC85A6170004BB709669C31DE94391A

这是因为这两个 CID 指向相同的内容,即本质上两个 CID 代表的是相同的哈希。



4.3 转换 CID 的版本

我们可以将任何的 CIDv0 转换为 CIDv1,但不能将任何的 CIDv1 转换为 CIDv0 。这是由于 CIDv1 支持多编码和多基数,而 CIDv0 不支持。事实上,只有具有以下属性的 CIDv1 可以转换为 CIDv0:

  • 多基数 = base58btc
  • 多编码 = dag-pb
  • 多哈希算法 = sha2-256
  • 多哈希长度 = 32 字节

为了测试这个理论,你可以查看我们亲爱的 土豚 图片,它托管在 IPFS 网络上:

https://ipfs.io/ipfs/QmcRD4wkPPi6dig81r5sLj9Zm1gDCL4zgpEj9CfuRrGbzF

首先,从 URL 末尾复制 CID:

QmcRD4wkPPi6dig81r5sLj9Zm1gDCL4zgpEj9CfuRrGbzF

然后,将 CID 粘贴到 CID Inspector 工具中,并在页面底部找到等效的 CIDv1 值:

bafybeigrf2dwtpjkiovnigysyto3d55opf6qkdikx6d65onrqnfzwgdkfa

最后,将原始 URL 中的 CID 替换为转换后的 CID:

https://ipfs.io/ipfs/bafybeigrf2dwtpjkiovnigysyto3d55opf6qkdikx6d65onrqnfzwgdkfa

你应该看到的是相同的土豚图片。



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/5760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

『项目整理』易CAR通项目说明文档-我的第一款APP

『项目整理』易CAR通项目说明文档-我的第一款APP 项目介绍功能介绍技术栈介绍实现效果如何运行备注 项目介绍 易CAR通项目是我的第一个Android项目。是一款结合了AR技术的模仿懂车帝的看车软件。因为是初学&#xff0c;所示实现的效果差强人意&#xff0c;很多的功能界面只实现…

ICode国际青少年编程竞赛- Python-1级训练场-基础训练1

ICode国际青少年编程竞赛- Python-1级训练场-基础训练1 1、 Dev.step(4)2、 Dev.step(-4) Dev.step(8)3、 Dev.turnLeft() Dev.step(4)4、 Dev.step(3) Dev.turnLeft() Dev.step(-1) Dev.step(4)5、 Dev.step(-1) Dev.step(3) Dev.step(-2) Dev.turnLeft() Dev.step(…

Java_从入门到JavaEE_08

一、Eclipse开发工具的介绍 Eclipse工具简绍 Eclipse 是著名的跨平台的自由集成开发环境&#xff08;IDE&#xff09;。最初主要用来 Java 语言开发&#xff0c;但是目前亦有人通过插件使其作为其他计算机语言比如 C 和 Python 的开发工具。 下载与安装 下载&#xff1a; Ecli…

羊大师:羊奶奥秘孩子健康新选择

羊大师&#xff1a;羊奶奥秘孩子健康新选择 羊奶&#xff0c;这个古老而珍贵的营养源&#xff0c;近年来越来越受到家长们的关注。它不仅富含各种营养成分&#xff0c;而且具有独特的消化吸收优势&#xff0c;成为孩子们健康成长的新选择。 羊奶的脂肪球颗粒直径小&#xff0c…

手撕spring框架(3)

手撕spring框架&#xff08;3&#xff09; 相关系列 手撕spring框架&#xff08;1&#xff09; 手撕spring框架&#xff08;2&#xff09; InitializingBean 接口详解 什么是 InitializingBean 接口&#xff1f; InitializingBean 接口是 Spring 框架中的一个接口&#xff0c…

Pandas入门篇(三)-------数据可视化篇3(seaborn篇)(pandas完结撒花!!!)

目录 概述一、语法二、常用单变量绘图1. 直方图&#xff08;histplot&#xff09;2. 核密度预估图&#xff08;kdeplot&#xff09;3. 计数柱状图&#xff08;countplot&#xff09; 三、常用多变量绘图1.散点图(1) scatterplot(2)regplot 散点图拟合回归线(3)jointplot 散点图…

ELK Stack 8 接入ElasticFlow

介绍 Netflow v5 / v9 / v10&#xff08;IPFIX&#xff09;&#xff0c;支持大部分网络厂商及VMware的分布式交换机。 NetFlow是一种数据交换方式。Netflow提供网络流量的会话级视图&#xff0c;记录下每个TCP/IP事务的信息。当汇集起来时&#xff0c;它更加易于管理和易读。…

什么是红队?

美国国家安全数据遭到攻击数据泄露数据检测和响应&#xff1a;增强威胁情报和事件响应美国国际开发署进行的全球互联网审查人工智能战争的杀戮问题 微信搜索关注公众号&#xff1a;网络研究观&#xff0c;了解获取更多信息。 红队由安全专业人员组成&#xff0c;他们充当克服网…

Linux 第十八章

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;linux &#x1f525;座右铭&#xff1a;“不要等到什么都没有了…

React 之 Suspense

Suspense Suspense 组件我们并不陌生&#xff0c;中文名可以理解为暂停or悬停 , 在 React16 中我们通常在路由懒加载中配合 Lazy 组件一起使用 &#xff0c;当然这也是官方早起版本推荐的唯一用法。 那它暂停了什么&#xff1f; 进行异步网络请求&#xff0c;然后再拿到请求…

瑞_23种设计模式_解释器模式

文章目录 1 解释器模式&#xff08;Interpreter Pattern&#xff09;1.1 介绍1.2 概述1.2.1 文法&#xff08;语法&#xff09;规则1.2.2 抽象语法树 1.3 解释器模式的结构1.4 解释器模式的优缺点1.5 解释器模式的使用场景 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代…

STM32 DMA直接存储器存取

单片机学习&#xff01; 目录 文章目录 前言 一、DMA简介 1.1 DMA是什么 1.2 DMA作用 1.3 DMA通道 1.4 软硬件触发 1.5 芯片资源 二、存储器映像 2.1 存储器 2.2 STM32存储器 三、DMA框图 3.1 内核与存储器 3.2 寄存器 3.3 DMA数据转运 3.4 DMA总线作用 3.5 DMA请求 3.6 DMA结构…

上位机图像处理和嵌入式模块部署(树莓派4b读写json数据)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;ini文件是用来进行配置的&#xff0c;数据库是用来进行数据存储的。那json是用来做什么的呢&#xff0c;json一般是用来做…

【JavaEE】线程的概念

文章目录 1、什么是线程2、进程和线程的区别3、多线程的概述4、在Java中实现多线程的方法1.继承Thread类2.实现Runnable接口3.使用匿名内部类来继承Thread类&#xff0c;实现run方法4.使用匿名内部类来实现Runnable接口&#xff0c;实现run方法5.使用 lambda表达式 1、什么是线…

【R语言数据分析】数据类型与数据结构

目录 对数据框的基本操作 创建矩阵 列表 字符串 日期变量与时间变量 缺失值NA 缺失值NA的处理 重新编码 R的数据类型有数值型num&#xff0c;字符型chr&#xff0c;逻辑型logi等等。 R最常处理的数据结构是&#xff1a;向量&#xff0c;数据框&#xff0c;矩阵&#x…

JAVA第二周学习笔记

文章目录 JAVA第二周学习笔记IDEA方法格式带参数及返回值的方法方法的重载方法的内存 二维数组静态初始化动态初始化 面向对象类和对象如何定义类如何得到对象注意 封装封装的优点private关键字成员变量和局部变量 this关键字构造方法作用类型特点执行时机定义重载 标准javabea…

neo4j 的插入速度为什么越来越慢,可能是使用了过多图谱查询操作

文章目录 背景描述分析解决代码参考neo4j 工具类Neo4jDriver知识图谱构建效果GuihuaNeo4jClass 背景描述 使用 tqdm 显示&#xff0c;处理的速度&#xff1b; 笔者使用 py2neo库&#xff0c;调用 neo4j 的API 完成节点插入&#xff1b; 有80万条数据需要插入到neo4j图数据中&am…

FANUC机器人SOCKET断开KAREL程序编写

一、添加一个.KL文件创建编辑断开指令 添加一个KL文件用来创建karel程序中socket断开指令 二、断开连接程序karel代码 PROGRAM SOC_DIS %COMMENT SOCKET断开 %INCLUDE klevccdf VAR str_input,str_val : STRING[20] status,data_type,int_val : INTEGER rel_val : REALBEGING…

【氮化镓】GaN器件在航天器高可靠正向转换器中应用

文章是发表在《IEEE Journal of Emerging and Selected Topics in Power Electronics》2022年10月第10卷第5期上的一篇关于GaN(氮化镓)器件在航天器高可靠性正向转换器中应用的研究。文章的作者是匹兹堡大学电气与计算机工程系的Aidan Phillips, Thomas Cook和Brandon M. Gra…

Android AOSP探索之Ubantu下Toolbox的安装

文章目录 概述安装Toolbox解决运行的问题 概述 由于最近需要进军android的framework,所以需要工具的支持&#xff0c;之前听说江湖上都流传source insight,我去弄了一个破解版&#xff0c;功能确实强大&#xff0c;但是作为多年android开发的我习惯使用android studio。虽然使…