- 区块链
- 密码学
【免费下载链接】fabric
Hyperledger Fabric is an enterprise-grade permissioned distributed ledger framework for developing solutions and applications. Its modular and versatile design satisfies a broad range of industry use cases. It offers a unique approach to consensus that enables performance at scale while preserving privacy.
导读
IBM mathlib 是一个面向配对友好椭圆曲线(pairing-friendly elliptic curves)的高性能 Go 密码学库,为基于配对的密码协议(零知识证明、匿名凭证、BLS 签名等)提供统一的编程接口。在 Hyperledger Fabric 仓库中,它以 v0.3.1 版本作为间接依赖随 vendor 目录一并分发。读完本文,你将掌握 mathlib 支持的曲线族与后端架构、核心类型(G1/G2/Gt/Zr)的用法、序列化与哈希到曲线等关键 API,并能通过源码级证据理解其驱动(driver)设计模式与性能要点。
库的定位与在 Fabric 仓库中的角色
mathlib 的设计目标,是把配对运算(pairing operation)的底层复杂性抽象掉,同时让上层应用能够根据性能与安全需求自由选择不同的曲线类型与后端实现。它支持以下典型密码协议:
- 零知识证明(Zero-knowledge proofs)
- 匿名凭证(Anonymous credentials)
在当前 Fabric 仓库中,mathlib 并非被 peer 或 orderer 源码直接 import,而是以间接依赖的形式打包在 vendor/modules.txt(标记为github.com/IBM/mathlib v0.3.1,模块声明为 go 1.26.3),并通过 vendor 目录提供完整的库源码、Makefile 与 LICENSE。这意味着任何对 pairing 运算有需求的 Fabric 依赖链模块都可以直接消费这套统一 API,无需各自对接不同的底层椭圆曲线库。
核心特性一览
从 README 与源码可以归纳出库的六大特性:
- 多种曲线支持:FP256BN、BN254、BLS12-381、BLS12-377 及 BBS+ 变体;
- 可插拔后端:支持 AMCL 与 Gurvy 两套实现;
- 类型安全 API:强类型的群元素(G1、G2、Gt、Zr),编译期即可避免混用不同群元素的错误;
- 高效运算:优化的配对计算与多标量乘(multi-scalar multiplication);
- 序列化:同时支持压缩与非压缩点表示;
- 哈希到曲线:支持可选域分离(domain separation)的曲线点安全哈希;
- 模运算:完整的标量域(scalar field)运算。
安装与运行环境要求
在任意 Go 工程中安装:
go get github.com/IBM/mathlib运行环境要求:README 声明需要 Go 1.25 或更高版本;而在本仓库的 vendor/modules.txt 中,mathlib v0.3.1 的模块标记为go 1.26.3,因此若在 Fabric 的 vendor 构建环境中使用,请确保工具链不低于此标记版本。
快速开始:五分钟跑通配对运算
下面的完整示例演示了选择曲线、生成随机标量、执行 G1 标量乘与配对,并在目标群中做乘法:
package main import ( "fmt" "github.com/IBM/mathlib" ) func main() { // Select a curve (BLS12-381 in this example) curve := math.Curves[math.BLS12_381] // Generate random scalars rng, _ := curve.Rand() a := curve.NewRandomZr(rng) b := curve.NewRandomZr(rng) // Perform scalar multiplication on G1 P := curve.GenG1.Mul(a) Q := curve.GenG1.Mul(b) // Compute pairing e1 := curve.Pairing(curve.GenG2, P) e2 := curve.Pairing(curve.GenG2, Q) // Multiply in target group e1.Mul(e2) fmt.Printf("Pairing result: %s\n", e1.String()) }从 math.go 源码可以看到,Curves是一个在包初始化阶段就完全构造好的[]*Curve切片,Curves[BLS12_381]直接返回已就绪的曲线实例,无需额外初始化;Rand()返回密码学安全的随机数源(io.Reader),NewRandomZr产生的标量在[0, group order)区间内均匀分布。
支持的曲线族与选型指南
| 曲线 ID | 说明 | 后端 | 典型用途 |
|---|---|---|---|
FP256BN_AMCL | 256 位 Barreto-Naehrig 曲线 | AMCL | 通用配对运算 |
FP256BN_AMCL_MIRACL | 256 位 BN 曲线(MIRACL 变体) | AMCL | 遗留系统兼容 |
BN254 | 254 位 Barreto-Naehrig 曲线 | Gurvy | 高性能应用 |
BLS12_381 | BLS12-381 曲线 | Gurvy | 现代协议、BLS 签名 |
BLS12_381_GURVY | BLS12-381 曲线 | Gurvy | 性能优化的 BLS12-381 |
BLS12_377_GURVY | BLS12-377 曲线 | Gurvy | 递归证明系统 |
BLS12_381_BBS | 面向 BBS+ 签名的 BLS12-381 | Gurvy | 匿名凭证 |
BLS12_381_BBS_GURVY | 面向 BBS+ 签名的 BLS12-381 | Gurvy | 高性能 BBS+ |
重要说明:
BLS12_381与BLS12_381_BBS此前由 Kilic 实现作为后端,现改为 Gurvy(gnark-crypto)实现,并保持与此前输出及显式_GURVY同名曲线的字节兼容(byte-compatible)。
如何选择曲线
- BLS12-381:新项目首选,标准化程度高、安全边际优秀;
- BN254:性能好,但安全边际比 BLS12-381 更紧;
- BLS12-377:专为递归证明组合(如 zk-SNARK)设计;
- BBS+ 变体:针对 BBS+ 签名方案专门优化(匿名凭证场景)。
从源码看曲线注册
在 math.go 中,每种曲线由一个CurveID常量标识(FP256BN_AMCL、BN254、FP256BN_AMCL_MIRACL、BLS12_381、BLS12_377_GURVY、BLS12_381_GURVY、BLS12_381_BBS、BLS12_381_BBS_GURVY),CurveIDToString负责转换为可读字符串(未知 ID 会 panic)。Curves切片按这些常量顺序注册了预配置实例,例如BLS12_381与BLS12_381_GURVY底层都使用bls12381.NewCurve(),而BLS12_381_BBS与BLS12_381_BBS_GURVY则使用bls12381.NewBBSCurve()——两者的区别仅在HashToG1/HashToG2遵循不同规范。
核心 API 类型与关键操作
四种核心类型
Curve:曲线操作的主接口,提供群元素的工厂方法、配对运算、哈希到曲线与模运算。每个实例封装了三个群的生成元(GenG1、GenG2、GenGt)、群阶(GroupOrder)以及序列化字节长度元数据(CoordByteSize、G1ByteSize、CompressedG1ByteSize、G2ByteSize、CompressedG2ByteSize、ScalarByteSize);Zr:标量域元素(模曲线阶的整数),支持加、减、乘、模逆、幂等运算,并提供与big.Int、int64、uint64、字节流的互转;G1:第一椭圆曲线群上的点,通常用于签名与承诺,也是配对函数的第一个参数;G2:第二椭圆曲线群(扭曲曲线)上的点,在许多协议中公钥位于 G2、签名位于 G1;Gt:目标群元素(配对运算的结果),支持乘法、幂与求逆。
关键操作速查
// Curve selection curve := math.Curves[math.BLS12_381] // Scalar operations a := curve.NewZrFromInt(42) b := curve.HashToZr([]byte("some data")) c := a.Plus(b) // G1 operations P := curve.GenG1.Mul(a) Q := curve.HashToG1([]byte("hash to point")) P.Add(Q) // G2 operations R := curve.GenG2.Mul(b) // Pairing e := curve.Pairing(R, P) // Target group operations e2 := e.Exp(c)源码级要点
- 反序列化安全:
NewG1FromBytes、NewG2FromBytes、NewG1FromCompressed、NewG2FromCompressed、NewGtFromBytes均在内部用defer/recover捕获底层驱动的 panic 并转为 error 返回,避免非法字节导致进程崩溃(见 math.go); - 带域分离的哈希:
HashToG1WithDomain/HashToG2WithDomain在域参数超过 255 字节等输入被底层拒绝时返回nil而非 panic(见 math.go); - 配对双线性:
Pairing(a, b)计算e(a, b),满足双线性性质e([x]a, [y]b) = e(a, b)^(xy);Pairing2一次计算两个配对之积e(p,q)·e(r,s),比两次单独配对更高效; - 多标量乘:
MultiScalarMul(points, scalars)计算[b0]a0 + [b1]a1 + ... + [bn]an,要求两个切片等长,比逐个标量乘再相加显著更快; - 线程安全:包注释明确说明库内类型不是线程安全的,跨 goroutine 共享实例时须由使用者自行加锁(见 math.go)。
实战示例:四个完整用例
示例 1:基本配对运算与双线性验证
curve := math.Curves[math.BLS12_381] // Create scalars a := curve.NewZrFromInt(5) b := curve.NewZrFromInt(7) // Compute [a]G1 and [b]G2 P := curve.GenG1.Mul(a) Q := curve.GenG2.Mul(b) // Compute pairing e([b]G2, [a]G1) result := curve.Pairing(Q, P) // Verify bilinearity: e(G2, [ab]G1) == e([b]G2, [a]G1) ab := a.Mul(b) expected := curve.Pairing(curve.GenG2, curve.GenG1.Mul(ab)) if result.Equals(expected) { fmt.Println("Pairing bilinearity verified!") }这个示例正好印证了源码注释中的双线性性质定义:把标量乘从两个参数分别移到一侧后,配对结果保持不变。
示例 2:序列化与反序列化(压缩与非压缩)
curve := math.Curves[math.BLS12_381] // Create a point rng, _ := curve.Rand() scalar := curve.NewRandomZr(rng) point := curve.GenG1.Mul(scalar) // Serialize (uncompressed) bytes := point.Bytes() // Deserialize recovered, err := curve.NewG1FromBytes(bytes) if err != nil { panic(err) } // Serialize (compressed) compressed := point.Compressed() recoveredCompressed, err := curve.NewG1FromCompressed(compressed) if err != nil { panic(err) } fmt.Printf("Original and recovered points match: %v\n", point.Equals(recovered) && point.Equals(recoveredCompressed))压缩格式大约只占用非压缩格式一半的空间(见 math.go 中Bytes与Compressed的注释),在带宽受限的分布式系统中尤为重要。每种曲线的精确字节长度可通过Curve上的G1ByteSize、CompressedG1ByteSize、G2ByteSize、CompressedG2ByteSize、ScalarByteSize字段查询。
示例 3:带域分离的哈希到曲线与签名雏形
curve := math.Curves[math.BLS12_381] // Hash to G1 with domain separation message := []byte("sign this message") domain := []byte("my-application-v1") point := curve.HashToG1WithDomain(message, domain) // Use in signature scheme rng, _ := curve.Rand() secretKey := curve.NewRandomZr(rng) signature := point.Mul(secretKey) fmt.Printf("Signature: %x\n", signature.Compressed())域分离参数用于避免不同协议或上下文之间的哈希碰撞(见 math.go)。值得注意的是HashToG1WithDomain在底层拒绝输入时会返回nil而非 panic,因此生产代码应对返回的指针做非空判断。
示例 4:多标量乘(Multi-Scalar Multiplication)
curve := math.Curves[math.BLS12_381] // Create multiple points and scalars points := []*math.G1{ curve.GenG1, curve.HashToG1([]byte("point2")), curve.HashToG1([]byte("point3")), } scalars := []*math.Zr{ curve.NewZrFromInt(2), curve.NewZrFromInt(3), curve.NewZrFromInt(5), } // Efficient multi-scalar multiplication: [2]P1 + [3]P2 + [5]P3 result := curve.MultiScalarMul(points, scalars) fmt.Printf("Multi-scalar multiplication result: %s\n", result.String())多标量乘在 zk-SNARK 验证、聚合签名等需要一次性计算大量点标量组合的场景中是关键性能优化手段(见 math.go 的接口实现)。
架构:驱动(Driver)模式
mathlib 采用驱动模式支持多后端实现,分层结构如下:
┌─────────────────────────────────────┐ │ mathlib (Public API) │ │ Curve, G1, G2, Gt, Zr types │ └─────────────────┬───────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ driver (Interface Layer) │ │ Curve, G1, G2, Gt, Zr interfaces │ └─────────────────┬───────────────────┘ │ ┌─────────┴─────────┐ ▼ ▼ ┌──────┐ ┌──────┐ │ AMCL │ │Gurvy │ └──────┘ └──────┘这一设计带来三点收益:
- 灵活性:新增曲线实现只需实现接口即可接入;
- 性能:可按用例选择最快的后端;
- 兼容性:支持对接不同的底层密码学库。
接口层与后端实现
接口层定义在 driver/math.go:Curve接口包含配对(Pairing、Pairing2、FExp)、群元素工厂、哈希到曲线、序列化字节长度、ModAddMul*系列模运算以及MultiScalarMul等约四十个方法;Zr、G1、G2、Gt四个接口则分别约束标量域、两个椭圆曲线群与目标群的行为。后端只需实现这五个接口并在 math.go 的Curves切片中注册,即可被上层统一使用。
当前两个后端实现位于 driver/amcl 与 driver/gurvy:
- AMCL(Apache Milagro Crypto Library):成熟、经过充分测试的实现,承载 FP256BN 系列曲线;
- Gurvy(gnark-crypto):高性能的 Go 原生实现,带汇编优化,支撑所有 BLS12-381、BLS12-377 与 BN254 曲线。
性能优化要点
- 带宽受限时优先使用压缩点序列化(
Compressed()/NewG1FromCompressed); - 双配对场景优先使用
Pairing2(比两次独立配对再相乘更高效); - 多个标量乘场景使用
MultiScalarMul(比逐个运算更快); - 在 G1 上做
[e]P + [f]Q组合运算时,考虑Mul2与Mul2InPlace。需注意:在 gnark 后端上Mul2的分配远少于两次独立Mul加一次Add,但由于其使用的联合 Strauss-Shamir 技术放弃了 GLV 自同态加速,墙钟时间与朴素的"两次 Mul + 一次 Add"相当(见 math.go 的详细注释); - 对绝大多数应用而言,Gurvy 后端的 BLS12-381 已提供出色的性能。
测试与基准
在库目录下运行:
make unit-tests # 运行单元测试 make perf # 运行基准测试本仓库的 vendor 目录中自带 Makefile,可据此查看完整的测试与性能目标定义。提交代码前建议运行make checks与make lint。
安全注意事项
- 始终使用密码学安全的随机数生成器(如
curve.Rand()提供的源); - 反序列化的点会被库自动校验(
NewG1FromBytes等接口内部以 panic 转 error 的方式兜底),但调用方仍应处理返回的 error; - 根据自身安全需求选择合适的曲线参数(如新项目优先 BLS12-381);
- 对敏感运算考虑计时攻击缓解措施(timing attack mitigations);
- 及时更新依赖,并牢记库内类型非线程安全,跨 goroutine 共享时自行同步。
许可证
mathlib 采用 Apache License 2.0 许可,详见 vendor/github.com/IBM/mathlib/LICENSE。本仓库的 LICENSE 文件中同时包含 Apache 2.0 全文,可对照查阅条款细节。
- 区块链
- 密码学
【免费下载链接】fabric
Hyperledger Fabric is an enterprise-grade permissioned distributed ledger framework for developing solutions and applications. Its modular and versatile design satisfies a broad range of industry use cases. It offers a unique approach to consensus that enables performance at scale while preserving privacy.
相关推荐
解密Maxun安全基石:ENCRYPTION_KEY长度背后的密码学逻辑
解密Maxun安全基石:ENCRYPTION_KEY长度背后的密码学逻辑 在当今数据驱动的时代,Web数据提取平台的安全性至关重要。Maxun作为一款开源无代码
后端前端网页爬虫低代码AI 应用V 语言 crypto 密码学模块实战指南:从对称加密到密码散列与密钥派生
V 语言 crypto 密码学模块实战指南:从对称加密到密码散列与密钥派生 vlib/crypto 是 V 语言标准库中对外提供密码学算法的模块集合,涵盖 AE
编程语言编译器语言运行时标准库JCSprout安全编码指南:密码学基础与实战应用
JCSprout安全编码指南:密码学基础与实战应用 在当今数字化时代, 安全编码 和 密码学基础 已成为Java开发者的必备技能。JCSprout项目作为Jav
文档知识库后端教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考