首頁  >  文章  >  後端開發  >  如何協調 Ed25519 的 Golang 和 Bittorrent 私鑰格式之間的差異?

如何協調 Ed25519 的 Golang 和 Bittorrent 私鑰格式之間的差異?

DDD
DDD原創
2024-10-31 07:06:30521瀏覽

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 個私密金鑰是64-雜湊的位元組輸出,或者可能只是以與雜湊結果相同的方式使用的64 個隨機位元組。

將 Bittorrent 金鑰轉換為 Golang 格式

不幸的是,將 Bittorrent 金鑰轉換為 Golang 格式是不可行的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