Documentation
¶
Overview ¶
Package sm3merkle 实现基于 SM3(GB/T 32905-2016)的 RFC 6962 Merkle 树。
哈希策略与 RFC 6962 完全一致,只把 SHA-256 换成 SM3:
空树根 = SM3() 叶子节点 = SM3(0x00 || 数据) 内部节点 = SM3(0x01 || 左子哈希 || 右子哈希)
0x00 / 0x01 前缀是域分离标记,用来阻断第二原像攻击——没有它, 攻击者可以把一个内部节点的哈希冒充成某个叶子的哈希。
证明的生成与校验直接复用 github.com/transparency-dev/merkle (Certificate Transparency 的上游实现),本包只提供 SM3 哈希层和 一棵内存树,不重写任何 Merkle 数学。
Example (Consistency) ¶
一致性证明用来确认日志只做了追加,历史条目没有被悄悄改写。
package main
import (
"fmt"
"github.com/LR2006-Robot/sm3merkle"
)
func main() {
tree := sm3merkle.New()
for _, entry := range []string{"v1", "v2", "v3"} {
tree.Append([]byte(entry))
}
oldSize, oldRoot := tree.Size(), tree.Root()
for _, entry := range []string{"v4", "v5"} {
tree.Append([]byte(entry))
}
newSize, newRoot := tree.Size(), tree.Root()
pf, err := tree.ConsistencyProof(oldSize, newSize)
if err != nil {
panic(err)
}
err = sm3merkle.VerifyConsistency(oldSize, newSize, pf, oldRoot, newRoot)
fmt.Println("仅追加校验:", err)
}
Output: 仅追加校验: <nil>
Example (Inclusion) ¶
日志方追加数据、发布树根,审计方只凭树根和证明验证某条数据确实在日志里。
package main
import (
"fmt"
"github.com/LR2006-Robot/sm3merkle"
)
func main() {
tree := sm3merkle.New()
for _, entry := range []string{"cert-A", "cert-B", "cert-C", "cert-D"} {
tree.Append([]byte(entry))
}
size := tree.Size()
root := tree.Root() // 对外发布的树根(实际场景中由 SM2 签名背书)
// 证明第 2 条数据在日志中。
pf, err := tree.InclusionProof(2, size)
if err != nil {
panic(err)
}
// 审计方手里只有 root、size 和这份证明。
err = sm3merkle.VerifyInclusionData(2, size, []byte("cert-C"), pf, root)
fmt.Println("cert-C 校验:", err)
err = sm3merkle.VerifyInclusionData(2, size, []byte("cert-X"), pf, root)
fmt.Println("伪造数据校验通过:", err == nil)
}
Output: cert-C 校验: <nil> 伪造数据校验通过: false
Index ¶
- Constants
- Variables
- func VerifyConsistency(size1, size2 uint64, pf [][]byte, root1, root2 []byte) error
- func VerifyInclusion(index, size uint64, leafHash []byte, pf [][]byte, root []byte) error
- func VerifyInclusionData(index, size uint64, data []byte, pf [][]byte, root []byte) error
- type Hasher
- type Tree
- func (t *Tree) Append(data []byte) uint64
- func (t *Tree) AppendHash(leafHash []byte) (uint64, error)
- func (t *Tree) ConsistencyProof(size1, size2 uint64) ([][]byte, error)
- func (t *Tree) InclusionProof(index, size uint64) ([][]byte, error)
- func (t *Tree) LeafHash(index uint64) ([]byte, error)
- func (t *Tree) Root() []byte
- func (t *Tree) RootAt(size uint64) ([]byte, error)
- func (t *Tree) Size() uint64
Examples ¶
Constants ¶
const ( LeafPrefix = 0x00 NodePrefix = 0x01 )
RFC 6962 域分离前缀。
const HashSize = sm3.Size
HashSize 是 SM3 摘要长度,32 字节。
Variables ¶
var DefaultHasher = Hasher{}
DefaultHasher 是本包各处默认使用的 SM3 哈希器。
Functions ¶
func VerifyConsistency ¶
VerifyConsistency 校验一致性证明:根为 root1、大小为 size1 的树, 是根为 root2、大小为 size2 的树的前缀。校验通过返回 nil。
func VerifyInclusion ¶
VerifyInclusion 校验包含证明:leafHash 确实是大小为 size 的树中下标 index 的叶子, 且该树的根为 root。校验通过返回 nil。
Types ¶
type Hasher ¶
type Hasher struct{}
Hasher 是 SM3 版本的 RFC 6962 哈希策略,实现 merkle.LogHasher。
func (Hasher) HashChildren ¶
HashChildren 返回内部节点哈希 SM3(0x01 || l || r)。
type Tree ¶
type Tree struct {
// contains filtered or unexported fields
}
Tree 是一棵仅追加(append-only)的内存 Merkle 树。
零值不可用,请用 New 或 NewWithHasher 构造。Tree 不是并发安全的, 多 goroutine 访问需自行加锁。
ponytail: 全部节点哈希常驻内存,约 2*N 个哈希,每个连 []byte 切片头约 56 字节, 实测百万叶子约 114MB。 日志规模超出内存时,改用 compact.Range 配合外部节点存储(见 docs/USAGE.md “超出内存的日志”一节),本包的 Hasher 可以原样复用。
func NewWithHasher ¶
NewWithHasher 用指定哈希策略构造空树。
正常使用国密场景请用 New。这个入口的存在是为了能塞入 RFC 6962 的 SHA-256 哈希器,拿 CT 官方黄金向量验证树本身的逻辑(见 tree_test.go)。
func (*Tree) AppendHash ¶
AppendHash 追加一个已经算好的叶子哈希,返回它的下标。
用于从持久化存储重建整棵树:把库里存的叶子哈希按下标顺序喂进来即可, 不需要原始数据。
哈希长度必须等于 hasher 的 Size(),否则返回错误且树不被修改。这个检查 拦的是恢复路径上最坏的一类事故——存储里的字节被截断、或误把原始数据当 哈希传入时,树会静默地长出一个错误的根,所有证明随之失效却没有任何报错。 长度对但内容错仍然无法在这里发现,恢复后请比对树根与上次发布的值。
leafHash 会被复制一份,调用方可以安全地复用传入的缓冲区。
func (*Tree) ConsistencyProof ¶
ConsistencyProof 返回「大小 size1 的树是大小 size2 的树的前缀」的一致性证明, 要求 0 <= size1 <= size2 <= Size()。这是仅追加性质的证据:老根没被改写过。
func (*Tree) InclusionProof ¶
InclusionProof 返回「下标 index 的叶子确实在大小为 size 的树里」的包含证明, 要求 0 <= index < size <= Size()。
Directories
¶
| Path | Synopsis |
|---|---|
|
verify
|
|
|
dumpproofs
command
把本包算出的树根与包含证明打印出来,供 verify.py 与独立实现比对。
|
把本包算出的树根与包含证明打印出来,供 verify.py 与独立实现比对。 |