」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 如何協調 Ed25519 的 Golang 和 Bittorrent 私鑰格式之間的差異?

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

發佈於2024-11-08
瀏覽:901

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

ed25519.Public Result Discrepancy

ed25519.Public Result Discrepancy

問題是由 ed25519 私鑰的不同格式所引起的。金鑰以 32 位元組種子開始,使用 SHA512 進行雜湊處理以建立 64 位元組(在此過程中某些位元會翻轉)。

Golang 私鑰格式

Golang 私鑰格式由32 位元組種子與32 位元組公鑰連接而成key.

Bittorrent 私鑰格式

Bittorrent 私鑰是雜湊值的64 位元組輸出,或者可能只是64 個隨機字節,其使用方式與雜湊結果。

將 Bittorrent 金鑰轉換為 Golang 格式不幸的是,轉換不可行Bittorrent 金鑰轉換為 Golang API 接受的格式,因為雜湊過程不可逆。

測試向量的自訂Golang 實作

為了解決此問題,修改了版本基於內部套件golang.org/x/crypto/ed25519/internal/edwards25519的Golang函式庫可以是建立:

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[:]
}

func getPublicKey(privateKey []byte) []byte { var A edwards25519.ExtendedGroupElement var hBytes [32]位元組 複製(hBytes[:],私鑰) edwards25519.GeScalarMultBase(&A, &hBytes) var publicKeyBytes [32]位元組 A.ToBytes(&publicKeyBytes) 返回公鑰位元組[:] }

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
}

func sign(privateKey, publicKey, message []byte) []byte { var privateKeyA [32]位元組 copy(privateKeyA[:], privateKey) // 稍後我們需要將其放入陣列中 var messageDigest, hramDigest [64]位元組 h := sha512.New() h.Write(privateKey[32:]) h.Write(訊息) h.Sum(訊息摘要[:0]) var messageDigestReduced [32]位元組 edwards25519.ScReduce(&messageDigestReduced, &messageDigest) var R edwards25519.ExtendedGroupElement edwards25519.GeScalarMultBase(&R, &messageDigestReduced) var 編碼R [32]位元組 R.ToBytes(&encodedR) h.Reset() h.Write(encodedR[:]) h.Write(公鑰) h.Write(訊息) h.Sum(hramDigest[:0]) var hramDigestReduced [32]位元組 edwards25519.ScReduce(&hramDigestReduced, &hramDigest) var s [32]位元組 edwards25519.ScMulAdd(&s, &hramDigestReduced, &privateKeyA, &messageDigestReduced) 簽章 := make([]byte, 64) 複製(簽名[:],編碼R[:]) 複製(簽名[32:],s[:]) 返回簽名 }

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!")))

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

用法範例

用法範例

用法範例

const privateKeyHex = “e06d3183d14159228433ed599221b80bd0a5ce8352e4b6 9d61e3b38e450a22e754941ac78479d6c54e1faf6037881d" const ExpectedPublicKey = "77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548" 常量預期訊號 = “6834284b6b24c3204eb2fea824d82f88883a3d95e8b4a21b8c0ded553d17d17d 87d9a08" privateKey, _ := hex.DecodeString(privateKeyHex) 公鑰 := getPublicKey(私鑰) keyMatches := ExpectedPublicKey == hex.EncodeToString(publicKey) sigMatches :=預期Sig == hex.EncodeToString(sign(privateKey, publicKey, []byte("4:salt6:foobar3:seqi1e1:v12:Hello World!")))

最新教學 更多>

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3