首页 > 后端开发 > Golang > 如何使用 Go 包 golang.org/x/crypto/ed25519 从预哈希私钥导出正确的公钥和签名?

如何使用 Go 包 golang.org/x/crypto/ed25519 从预哈希私钥导出正确的公钥和签名?

Susan Sarandon
发布: 2024-11-01 04:27:02
原创
697 人浏览过

How can I derive the correct public key and signature from a prehashed private key using the Go package golang.org/x/crypto/ed25519?

Ed25519 公钥不一致

问题描述:

使用 Go 包 golang.org/x/crypto/ed25519 ,与给定测试用例中定义的预期公钥相比,尝试从给定私钥派生公钥会产生不同的结果。

根本原因:

差异是由于使用不同的 ed25519 私钥格式而产生的。

私钥格式差异:

  • Go 包期望的私钥格式包括32 字节种子与 32 字节公钥连接。
  • 测试用例使用私钥格式,该格式是应用于种子的哈希的 64 字节结果(或者可能使用了 64 个随机字节)作为替代)。

解决方案:

由于反转用于生成测试用例私钥的哈希不可行,因此转换为与Go 包是不可能的。

建议的解决方案:

要获取测试用例的正确公钥,可以创建 Go 包的修改版本:使用以下自定义函数:

getPublicKey:

<code class="go">// GetPublicKey generates the public key from the prehashed private key.
func getPublicKey(privateKey []byte) []byte {
    var A edwards25519.ExtendedGroupElement
    var hBytes [32]byte
    copy(hBytes[:], privateKey)
    edwards25519.GeScalarMultBase(&A, &hBytes)
    var publicKeyBytes [32]byte
    A.ToBytes(&publicKeyBytes)
    return publicKeyBytes[:]
}</code>
登录后复制

sign:

<code class="go">// Sign generates a signature from the prehashed private key, public key, and message.
func sign(privateKey, publicKey, message []byte) []byte {
    var privateKeyA [32]byte
    copy(privateKeyA[:], privateKey)
    var messageDigest, hramDigest [64]byte
    h := sha512.New()
    h.Write(privateKey[32:])
    h.Write(message)
    h.Sum(messageDigest[:0])
    var messageDigestReduced [32]byte
    edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
    var R edwards25519.ExtendedGroupElement
    edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
    var encodedR [32]byte
    R.ToBytes(&encodedR)
    h.Reset()
    h.Write(encodedR[:])
    h.Write(publicKey)
    h.Write(message)
    h.Sum(hramDigest[:0])
    var hramDigestReduced [32]byte
    edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
    var s [32]byte
    edwards25519.ScMulAdd(&s, &hramDigestReduced, &privateKeyA, &messageDigestReduced)
    signature := make([]byte, 64)
    copy(signature[:], encodedR[:])
    copy(signature[32:], s[:])
    return signature
}</code>
登录后复制

用法示例:

<code class="go">privateKeyHex := "e06d3183d14159228433ed599221b80bd0a5ce8352e4bdf0262f76786ef1c74db7e7a9fea2c0eb269d61e3b38e450a22e754941ac78479d6c54e1faf6037881d"
privateKey, _ := hex.DecodeString(privateKeyHex)
expectedPublicKey := "77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548"
expectedSig := "6834284b6b24c3204eb2fea824d82f88883a3d95e8b4a21b8c0ded553d17d17ddf9a8a7104b1258f30bed3787e6cb896fca78c58f8e03b5f18f14951a87d9a08"
publicKey := getPublicKey(privateKey)
fmt.Printf("Calculated Public Key: %x\n", publicKey)
fmt.Printf("Expected Public Key:   %s\n", expectedPublicKey)
calculatedSig := sign(privateKey, publicKey, []byte("Hello, World!"))
fmt.Printf("Calculated Signature: %x\n", calculatedSig)
fmt.Printf("Expected Signature:   %s\n", expectedSig)</code>
登录后复制

此方法允许使用修改后的 Go 包计算正确的公钥和签名,如测试用例中所指定。

以上是如何使用 Go 包 golang.org/x/crypto/ed25519 从预哈希私钥导出正确的公钥和签名?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板