门限签名
概述
RSA 门限签名允许多个参与方在不暴露自己的私钥的情况下,分别用自己的私钥对一笔数据进行签名,在验证的时候,只需要获取一定数量签名(基于门限值的设定, 通常小于参与者的数量)就可以验证该笔数据的有效性。这提高了多方参与的效率和安全性。
goar 的 threshold.go 实现了门限签名算法,可以供开发者快速、便捷的生成密钥对,实现密钥分发,提高应用的安全性和可靠性。
使用
密钥生成
k := 3
l := 5
bitSize := 1024
keyShares, keyMeta, err := goar.CreateTcKeyPair(bitSize, k, l)
if err != nil {
panic(err)
}
fmt.Printf("%v\n%v", keyShares, keyMeta)
说明:
l
是参与者的数量。k
是门限值,本例中设置为 3,意味着在这个门限签名的应用案例中,参与方是 5,只需要获取其中任意 3 个参与方的签名就可以验证数据的有效性。bitSize
与密钥生成时 RSA 私钥的二进制长度相关,goar 将这个值限定在 [512,4096] 区间,因为该值太短会导致安全性的不足,太长能增加安全性但是密钥生成的效率会大大降低。在生产环境中,将这个值设置为 4096 是足够安全的。keyMeta
是生成的门限签名公钥,里面包含了 参与方数量l
和门限值k
,这个公钥会分发给所有的参与方。keyShares
是生成的分发密钥,这是一个数组,其长度为l
,数组中的每一个元素将会分别分发给所有的参与者,作为他们进行签名的私钥。
创建 TcSign 实例
data := []byte("data need to sign")
salt := sha256.Sum256([]byte("everHash salt aaa"))
ts, err := goar.NewTcSign(keyMeta, data, salt[:])
说明:
data
是需要签名的数据。salt
是添加的噪声。keyMeta
是生成门限签名时的公钥。
创建 TcSign 实例的主要作用是:
- 对于参与方来说,通过 keyMeta 创建一个 TcSign 实例后,才可以利用自己获得的分发密钥对数据进行签名,再将签名提交给验证者进行签名聚合和验证。
- 对于验证方来说,通过 keyMeta 创建一个 TcSign 实例后,才可以验证接收到的参与方的签名是否合法,若合法,则将合法的签名进行聚合,进行门限签名的验证。
下面分别介绍参与方与验证方如何使用 TcSign 实例。
参与方进行门限签名
ts, err := goar.NewTcSign(keyMeta, data, salt[:])
key := keyShares[0]
sig0, err := ts.ThresholdSign(key)
说明:
key
是编号为 0 的参与者获得的分发密钥,keyShares
是密钥生成步骤中为所有参与者生成的分发密钥。sig0
是编号为 0 的参与者对数据的签名。
参与者对数据进行门限签名后就可以将签名提交给验证者(签名聚合器)。
验证签名
signedShares := tcrsa.SigShareList{
sig0,
sig1,
sig2,
}
// assemble
signature, err := ts.AssembleSigShares(signedShares)
if err != nil {
panic(err)
}
// verify
signHashed := sha256.Sum256(data)
err = rsa.VerifyPSS(keyMeta.PublicKey, crypto.SHA256, signHashed[:], signature, nil)
说明:
signedShares
包含了参与者 0,1,2 对数据的签名。signature
是验证者对 0,1,2 号参与者的签名进行聚合后生成的签名。
在获取到聚合签名后,就可以对数据的签名进行合法性验证了,在本例中我们提供了三个参与者的签名,满足门限值 k 的设定。