首页 >后端开发 >Golang >如何协调 Ed25519 的 Golang 和 Bittorrent 私钥格式之间的差异?

如何协调 Ed25519 的 Golang 和 Bittorrent 私钥格式之间的差异?

DDD
DDD原创
2024-10-31 07:06:30602浏览

How to reconcile the discrepancy between Golang and Bittorrent private key formats for Ed25519?

ed25519.公共结果差异

问题是由 ed25519 私钥的不同格式引起的。密钥以 32 字节种子开始,使用 SHA512 进行哈希处理以创建 64 字节(在此过程中某些位会翻转)。

Golang 私钥格式

Golang 私钥格式由 32 字节种子与 32 字节公钥连接而成

Bittorrent 私钥格式

Bittorrent 私钥是哈希值的 64 字节输出,或者可能只是 64 个随机字节,其使用方式与哈希结果。

将 Bittorrent 密钥转换为 Golang格式

不幸的是,将 Bittorrent 密钥转换为 Golang API 接受的格式是不可行的,因为哈希过程是不可逆的。

测试向量的自定义 Golang 实现

为了解决这个问题,基于内部包的Golang库的修改版本golang.org/x/crypto/ed25519/internal/edwards25519 可以创建:

从私钥生成公钥的函数

<code class="go">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>

函数签名生成

<code class="go">func sign(privateKey, publicKey, message []byte) []byte {

    var privateKeyA [32]byte
    copy(privateKeyA[:], privateKey) // we need this in an array later
    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">const privateKeyHex = "e06d3183d14159228433ed599221b80bd0a5ce8352e4bdf0262f76786ef1c74db7e7a9fea2c0eb269d61e3b38e450a22e754941ac78479d6c54e1faf6037881d"

const expectedPublicKey = "77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548"
const expectedSig = "6834284b6b24c3204eb2fea824d82f88883a3d95e8b4a21b8c0ded553d17d17ddf9a8a7104b1258f30bed3787e6cb896fca78c58f8e03b5f18f14951a87d9a08"

privateKey, _ := hex.DecodeString(privateKeyHex)
publicKey := getPublicKey(privateKey)

keyMatches := expectedPublicKey == hex.EncodeToString(publicKey)
sigMatches := expectedSig == hex.EncodeToString(sign(privateKey, publicKey, []byte("4:salt6:foobar3:seqi1e1:v12:Hello World!")))</code>

以上是如何协调 Ed25519 的 Golang 和 Bittorrent 私钥格式之间的差异?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn