「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > Ed25519 の Golang と Bittorrent の秘密鍵形式の不一致を調整するにはどうすればよいですか?

Ed25519 の Golang と Bittorrent の秘密鍵形式の不一致を調整するにはどうすればよいですか?

2024 年 11 月 8 日に公開
ブラウズ:395

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

ed25519.公開結果の不一致

この問題は、ed25519 秘密鍵の形式が異なるために発生します。キーは 32 バイトのシードとして開始され、SHA512 を使用してハッシュされて 64 バイトが作成されます (このプロセス中に特定のビットが反転されます)。

Golang 秘密キー形式

Golang 秘密キー形式は、32 バイトの公開キーと連結された 32 バイトのシードで構成されます。 key.

Bittorrent 秘密キーの形式

Bittorrent 秘密キーは、ハッシュの 64 バイト出力、または潜在的にはハッシュと同じ方法で使用される単なる 64 ランダム バイトです。ハッシュ結果。

Bittorrent キーを Golang に変換する形式

残念ながら、ハッシュ プロセスは元に戻せないため、Bittorrent キーを Golang API が受け入れる形式に変換することは現実的ではありません。

テスト ベクター用のカスタム Golang 実装

この問題に対処するために、内部パッケージに基づいた Golang ライブラリの修正バージョンが追加されました。 golang.org/x/crypto/ed25519/internal/edwards25519 を作成できます:

秘密キーから公開キーを生成する関数

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 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
}

使用例

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!")))
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3