Skip to main content

Bip32

基于椭圆曲线密码学

tsskey_test.go

https://github.com/okx/threshold-lib/blob/main/tss/key/bip32/tsskey_test.go

package bip32

import (
"encoding/hex"
"fmt"
"math/big"
"testing"

"github.com/decred/dcrd/dcrec/secp256k1/v2"
"github.com/okx/threshold-lib/crypto"
"github.com/okx/threshold-lib/crypto/curves"
)

// 目的是验证密钥派生链是否按预期工作,并确保每一步的派生都能正确计算出新的公钥和私钥份额
func TestTssKey(t *testing.T) {
curve := secp256k1.S256()
x := crypto.RandomNum(curve.N)
X := curves.ScalarToPoint(curve, x)
chaincode := hex.EncodeToString([]byte("chaincode"))

tssKey, _ := NewTssKey(x, X, chaincode)
// /protocol/coinType/index
tssKey, _ = tssKey.NewChildKey(0)
tssKey, _ = tssKey.NewChildKey(0)
tssKey, _ = tssKey.NewChildKey(0)
fmt.Println("child publicKey: ", tssKey.PublicKey())
fmt.Println("child key share: ", tssKey.ShareI())
fmt.Println("privateKey offset: ", tssKey.PrivateKeyOffset())
childKey := new(big.Int).Mod(new(big.Int).Add(x, tssKey.PrivateKeyOffset()), curve.N)
fmt.Println("child key share: ", childKey)
}

// 这个测试用例主要用于验证即使在不知道原始私钥的情况下,只通过公钥和链码也能正确进行密钥派生,并且派生出的新公钥与通过计算得到的公钥一致。
func TestTssKey_cmp(t *testing.T) {
curve := secp256k1.S256()
x := crypto.RandomNum(curve.N) // 私钥
X := curves.ScalarToPoint(curve, x) // 公钥
chaincode := hex.EncodeToString([]byte("chaincode"))

tssKey, _ := NewTssKey(nil, X, chaincode)
fmt.Println(tssKey)
tssKey, _ = tssKey.NewChildKey(45)
fmt.Println(tssKey)

x_new := new(big.Int).Add(x, tssKey.PrivateKeyOffset()) // 新的私钥
X_new := curves.ScalarToPoint(curve, x_new) // 新的公钥
fmt.Println(tssKey.publicKey) // 旧的公钥
fmt.Println(X_new) // 新的公钥
}

这两个测试用例为了测试什么

这两个测试用例在 Go 语言中使用了testing框架,主要用于验证TssKey类和其方法(如密钥派生)的功能和正确性。下面我们逐一分析这两个测试用例的目的和执行内容:

TestTssKey

这个测试用例主要验证以下几点:

  1. 密钥初始化和派生过程

    • 使用随机生成的私钥x和相应的公钥X初始化TssKey
    • 连续进行三次非强化密钥派生,模拟一个多层次的密钥派生场景(例如,模拟路径m/0/0/0)。
  2. 输出验证

    • 打印最终派生出的子公钥、子私钥份额和累积的私钥偏移量。
    • 计算并打印出最终的私钥,这是通过将原始私钥和累积偏移量相加得到的。

这个测试用例的目的是验证密钥派生链是否按预期工作,并确保每一步的派生都能正确计算出新的公钥和私钥份额。

TestTssKey_cmp

这个测试用例的目的是比较和验证以下内容:

  1. 公钥一致性
    • 初始化TssKey时不传入原始私钥x,只传入公钥X和链码,然后进行一次密钥派生。
    • 计算派生后的新私钥x_new(原始私钥加上派生偏移量),并从此私钥生成新的公钥X_new
    • 比较TssKey中的公钥和通过新计算的公钥X_new,验证它们是否相同。

这个测试用例主要用于验证即使在不知道原始私钥的情况下,只通过公钥和链码也能正确进行密钥派生,并且派生出的新公钥与通过计算得到的公钥一致。

总结

这两个测试用例共同验证了TssKey的初始化、密钥派生功能的正确性,以及在不同输入条件下(有无私钥份额)公钥的一致性。这样的测试是确保密钥派生逻辑和实现的正确性和安全性的关键步骤。

确保每一步的派生都能正确计算出新的公钥和私钥份额

在密钥派生的上下文中,确保每一步的派生都能正确计算出新的公钥和私钥份额意味着验证以下几点:

  1. 公钥正确性

    • 在派生过程中,新的公钥是通过将原始公钥与基于派生路径和链码计算出的偏移量(一个椭圆曲线上的点)相加得到的。这个操作必须正确执行,以确保新的公钥在椭圆曲线上有效,并且正确地反映了派生路径的意图。
  2. 私钥份额的更新

    • 如果存在私钥份额(在阈值签名方案中,这是分散存储的私钥的一部分),在派生过程中,新的私钥份额是通过将原始私钥份额与派生过程中计算出的私钥偏移量相加得到的。这个偏移量是从 HMAC-SHA512 的结果中提取的前 32 字节转换而成的大整数。这个更新过程需要确保新的私钥份额在数学上是正确的,并且符合椭圆曲线密码学的要求。
  3. 累积的私钥偏移量

    • 在多层派生过程中,每一层派生都会产生一个新的偏移量,这些偏移量需要被累积(即连续相加)。这个累积值最终反映了从最初的私钥到当前派生私钥的完整偏移。这个值的正确计算对于最终确定整个密钥树的安全性至关重要。

在实际的应用场景中,这些计算需要非常精确和安全,因为任何错误都可能导致密钥不匹配,进而影响到加密系统的完整性和安全性。例如,如果公钥计算错误,可能导致无法正确验证数字签名;如果私钥份额计算错误,可能导致无法正确生成签名。因此,测试这些功能的正确性是密钥管理系统开发中的一个关键步骤。