Nix Hash v1 JSON 协议全解析:SRI 格式哈希的 Schema 规范与底层实现
2026/9/21 19:30:17 网站建设 项目流程
  • 开发工具
  • CLI

【免费下载链接】nix

Nix, the purely functional package manager

项目地址:https://gitcode.com/gh_mirrors/ni/nix
点击查看免费下载

导读

Hash v1hash-v1)是 Nix 协议族中定义"加密哈希值"JSON 表示的核心数据契约:它规定 Nix 内部所有以 JSON 传递的哈希值一律使用 SRI(Subresource Integrity) 字符串编码,形如sha256-<Base64>。这份 Schema 同时被内容寻址(Content Address)、存储对象信息(Store Object Info)等多个 JSON 协议引用,贯穿固定输出派生、NAR 哈希、下载校验等关键链路。读完本文,你将掌握 Hash v1 的完整 Schema 字段、SRI 格式的解析规则与算法约束,并能结合仓库源码理解其实现细节与验证方式。

Hash v1:Nix JSON 协议族中的基础数据类型

Nix 在 doc/manual/source/protocols/json 下维护了一批以 JSON Schema(Draft 04)形式定义的数据契约,包括file-system-object-v1hash-v1content-address-v1store-path-v1signature-v2store-object-info-v3derivation-v4等(见 meson.build)。hash-v1是其中最基础、复用面最广的类型之一。

定义该数据类型的唯一权威源文件是 schema/hash-v1.yaml,而 hash.md 是其面向读者的协议文档页面:主体通过{{#include hash-v1-fixed.md}}引入构建期生成的 Schema 文档,随后给出具体算法的 JSON 示例。

说明hash-v1-fixed.md是构建产物而非仓库内已提交文件。根据 meson.build,它由json-schema-for-humansgenerate-schema-doc)从hash-v1.yaml生成,再经fixup-json-schema-generated-doc.sed修正得到。若构建环境中未找到该工具,则会跳过生成并输出警告。

Schema 规范核心:一个 SRI 字符串

hash-v1.yamlHash类型的 JSON 表示做了三点核心约束:

type: string pattern: "^(blake3|md5|sha1|sha256|sha512)-[A-Za-z0-9+/]+=*$"
  • 类型必须是字符串type: string),不允许对象或数组结构;
  • 格式必须是 SRI 字符串<算法名>-<Base64 编码的哈希体>,算法名与哈希体之间用连字符-分隔;
  • 算法白名单blake3md5sha1sha256sha512,且算法名必须位于字符串开头。

Schema 的description明确指出:这是 NixHash类型以 SRI 字符串表示的 JSON 形式,用于"内容寻址与完整性验证"(content addressing and integrity verification)。

$defs.algorithm:算法枚举

Schema 还以$defs定义了可复用的algorithm子类型(schema/hash-v1.yaml#L14-L28):

algorithm: type: string enum: - blake3 - md5 - sha1 - sha256 - sha512

其中特别注明:blake3目前是实验性的,需要启用blake3-hashes实验特性(见下文"BLAKE3 实验特性"一节)。

各算法哈希长度与底层枚举

源码 src/libutil/include/nix/util/hash.hh#L14-L35 中定义了与 Schema 白名单一一对应的HashAlgorithm枚举及固定哈希长度:

算法名(SRI 前缀)枚举值哈希长度(字节)
md5MD516
sha1SHA120
sha256SHA25632
sha512SHA51264
blake3BLAKE332

Hash结构体(hash.hh#L57-L71)内部以uint8_t hash[maxHashSize]maxHashSize = 64)存放原始字节,并携带algo字段标注算法。长度约束在解析时会被严格执行:解码后的字节数与regularHashSize(algo)不符即抛出BadHash错误(见 src/libutil/hash.cc#L162-L164)。

SRI 格式的解析原理

Hash v1规定 SRI 字符串为唯一合法格式,其解析逻辑集中在 src/libutil/hash.cc#L171-L182 的Hash::parseSRI

  1. splitPrefixTo(rest, '-')从首个-处切分,取出算法名前缀;
  2. 通过parseHashAlgo将前缀字符串映射为HashAlgorithm枚举;
  3. 对剩余部分做 Base64 解码,并严格校验解码长度与regularHashSize一致;
  4. 拷贝进Hash结构体。

因此形如sha256-8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts=的字符串,会被解析为"算法sha256+ 32 字节原始哈希"。若缺少-分隔符或算法名不在白名单中,则会分别抛出"hash '%s' is not SRI"或"unknown hash algorithm"错误。

作为对照,Nix 内部通用的parseAny还额外支持type:hash(冒号前缀)、无前缀的 Base16/Nix32/Base64 等宽松输入(hash.cc#L192-L227)——但Hash v1 JSON Schema 只接受 SRI 一种,这与 JSON 交换场景下自描述、无歧义的需求一致。

BLAKE3 的实验性门控

parseHashAlgoOpt(src/libutil/hash.cc#L472-L487)对blake3做了特殊处理:解析到该算法时首先调用xpSettings.require(Xp::BLAKE3Hashes),未启用blake3-hashes实验特性会直接报错。该特性在 src/libutil/experimental-features.cc#L276-L282 中注册,描述为 "Enables support for BLAKE3 hashes."。

这也是 Schema 中注明blake3为实验性、需要实验特性的原因。BLAKE3 自 Nix 2.27 起加入(见 release-notes/rl-2.27.md),官方示例:

nix hash file ./file --type blake3 --extra-experimental-features blake3-hashes blake3-34P4p+iZXcbbyB1i4uoF7eWCGcZHjmaRn6Y7QdynLwU=

实现层面,BLAKE3 通过blake3_hasher计算,且对超过 128000 字节(blake3TbbThreshold,见 hash.cc#L321-L334)的大数据块会切换到 TBB 并行哈希(blake3_hasher_update_tbb)以提升吞吐。

官方示例 JSON

hash.md在 Schema 正文之后给出两个可直接复制的示例(与 src/json-schema-checks/hash 目录下的校验样例一致)。

SHA-256(schema/hash-v1/sha256.json)

"sha256-8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts="

BLAKE3(schema/hash-v1/blake3.json)

"blake3-nnDuFEmWX7YtBJBAoe0G7Dd0MNpuwTFz58T//NKL6YA="

注意示例中 SRI 哈希体的 Base64 尾部分别带有=填充(...W4Ts=)或无填充(...KL6YA=),与 Schema 正则中的=*$允许零个或多个=尾填充是一致的。

Hash v1 在协议族中的复用位置

hash-v1不是孤立定义,它被多个上层协议通过$ref引用:

  • Content Address v1(schema/content-address-v1.yaml#L30-L40):ContentAddress对象由methodflat/nar/text/git)与hash组成,hash字段即引用./hash-v1.yaml,表示文件系统对象的内容地址;
  • Store Object Info v3(schema/store-object-info-v3.yaml#L76-L80):narHash字段引用./hash-v1.yaml,表示存储对象序列化为 Nix Archive(NAR)后文件系统对象部分的哈希;其downloadHash字段(#L248-L250)同样复用 Hash v1。

这解释了 Hash v1 在整个 JSON 协议体系中的定位:它是任何需要表达哈希值字段时的标准类型,保证所有协议对"哈希长什么样"的理解完全一致。

验证机制:Schema 与示例的双重测试

仓库用jvjsonschema包提供的 JSON Schema 校验器)对 Hash v1 做了自动化测试,见 src/json-schema-checks/meson.build#L31-L38:

  • hash-schema-valid:校验hash-v1.yaml本身符合 JSON Schema Draft 04;
  • hash-example-sha256hash-example-blake3:分别用sha256.jsonblake3.json两个样例文件校验其能通过 Schema。

测试通过meson test --suite json-schema运行,或直接nix build .#nix-json-schema-checks(meson.build#L1-L4)。这意味着文档中展示的每一个示例都是经过 Schema 验证的真实合法值,可直接放心使用。

实战:生成与转换 SRI 哈希

Hash v1 的 SRI 字符串与 Nix 的命令行工具天然衔接。以nix-hash(见 command-ref/nix-hash.md)为例,默认输出十六进制,可用--sri直接产出 Hash v1 格式:

$ nix-hash --type sha1 --sri test/ sha1-5P2Lpfe76upazon+ECVVNs1g2rY=

若已有其他格式的哈希,可用--to-sri转换(SRI 哈希体为 Base64,--to-base16/--to-base32/--to-base64可反向转换到其他编码):

$ nix-hash --type sha1 --to-sri nvd61k9nalji1zl9rrdfmsmvyyjqpzg4 sha1-5P2Lpfe76upazon+ECVVNs1g2rY= $ nix-hash --to-base16 sha1-5P2Lpfe76upazon+ECVVNs1g2rY= e4fd8ba5f7bbeaea5ace89fe10255536cd60dab6

需要注意nix-hash默认计算的是路径的 NAR 序列化哈希(与nix-store --dump path | md5sum等价),--flat则直接哈希单个普通文件,结果与md5sum/sha1sum一致(nix-hash.md#L20-L40)。

在 Nix 表达式中的使用

Nix 语言层面的固定输出派生通过outputHashAlgo/outputHash表达同一概念:outputHashAlgo可取"blake3""sha1""sha256""sha512"null,且当outputHash使用 SRI 格式时outputHashAlgo必须为null——因为算法已由 SRI 前缀决定(见 language/advanced-attributes.md#L269-L272)。这与 Hash v1 "算法名内嵌于字符串"的设计一脉相承。

小结

Hash v1 是 Nix JSON 协议体系中"哈希值"的唯一标准形态:一个以算法名为前缀、Base64 为哈希体、由连字符连接的 SRI 字符串。其 Schema 约束(算法白名单、字符串类型、正则格式)与源码实现(parseSRI的严格长度校验、BLAKE3 的实验特性门控)相互印证;它被 Content Address 与 Store Object Info 等协议广泛复用,并有jv自动化测试兜底。无论是阅读 Nix 的 JSON 协议、编写解析器,还是手动校验narHashdownloadHash等字段,掌握 Hash v1 的规范都能让你快速、准确地理解数据的含义与合法性边界。

  • 开发工具
  • CLI

【免费下载链接】nix

Nix, the purely functional package manager

项目地址:https://gitcode.com/gh_mirrors/ni/nix
点击查看免费下载

相关推荐

上一篇:Claude Desktop for Linux终极指南:从零开始掌握Linux原生AI助手
下一篇:深度解析ZXing-CPP:GDI+ Bitmap数据转换的底层实现与性能优化

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询