Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapakah pelaksanaan Go ed25519 menjana kunci awam yang berbeza daripada yang dijangkakan dalam kes tertentu?

Mengapakah pelaksanaan Go ed25519 menjana kunci awam yang berbeza daripada yang dijangkakan dalam kes tertentu?

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-10-30 17:24:031001semak imbas

Why does the Go implementation of ed25519 generate a different public key than expected in certain cases?

ed25519 Ketaksamaan Penjanaan Kunci Awam

Pakej kriptografi ed25519 menyediakan cara menjana kunci awam daripada kunci persendirian. Walau bagaimanapun, pengguna telah melihat bahawa kunci awam yang dijana oleh pelaksanaan Go tidak sejajar dengan nilai yang dijangkakan dalam kes penggunaan tertentu.

Punca Punca:

Perbezaan ini timbul daripada format berbeza yang digunakan untuk mewakili kunci peribadi ed25519. Pakej Go menggunakan format di mana kunci persendirian diwakili sebagai gabungan benih 32 bait dan kunci awam 32 bait. Sebaliknya, vektor ujian yang mentakrifkan hasil yang dijangkakan mewakili kunci persendirian sebagai output 64-bait pencincangan benih.

Penyelesaian:

Memandangkan ia tidak boleh dilaksanakan untuk membalikkan proses pencincangan, adalah mustahil untuk menukar kunci peribadi vektor ujian kepada format yang serasi dengan pelaksanaan Go. Sebagai alternatif, anda boleh membuat versi pustaka Go yang diubah suai yang menyokong format kunci persendirian alternatif.

Kod Perpustakaan yang Diubah Suai:

Coretan kod berikut menyediakan versi tersuai pelaksanaan Go untuk menyokong format kunci persendirian ganti:

Menjana Kunci Awam:

<code class="go">// Generate the public key corresponding to the already hashed private
// key.
//
// This code is mostly copied from GenerateKey in the
// golang.org/x/crypto/ed25519 package, from after the SHA512
// calculation of the seed.
func getPublicKey(privateKey []byte) []byte {
    var A edwards25519.ExtendedGroupElement
    var hBytes [32]byte
    copy(hBytes[:], privateKey)
    edwards25519.GeScalarMultBase(&amp;A, &amp;hBytes)
    var publicKeyBytes [32]byte
    A.ToBytes(&amp;publicKeyBytes)

    return publicKeyBytes[:]
}</code>

Menandatangani:

<code class="go">// Calculate the signature from the (pre hashed) private key, public key
// and message.
//
// This code is mostly copied from the Sign function from
// golang.org/x/crypto/ed25519, from after the SHA512 calculation of the
// seed.
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(&amp;messageDigestReduced, &amp;messageDigest)
    var R edwards25519.ExtendedGroupElement
    edwards25519.GeScalarMultBase(&amp;R, &amp;messageDigestReduced)

    var encodedR [32]byte
    R.ToBytes(&amp;encodedR)

    h.Reset()
    h.Write(encodedR[:])
    h.Write(publicKey)
    h.Write(message)
    h.Sum(hramDigest[:0])
    var hramDigestReduced [32]byte
    edwards25519.ScReduce(&amp;hramDigestReduced, &amp;hramDigest)

    var s [32]byte
    edwards25519.ScMulAdd(&amp;s, &amp;hramDigestReduced, &amp;privateKeyA, &amp;messageDigestReduced)

    signature := make([]byte, 64)
    copy(signature[:], encodedR[:])
    copy(signature[32:], s[:])

    return signature
}</code>

Demonstrasi:

Kod berikut menunjukkan penggunaan fungsi tersuai untuk menjana kunci dan tandatangan awam yang dijangkakan:

<code class="go">privateKeyHex := "e06d3183d14159228433ed599221b80bd0a5ce8352e4bdf0262f76786ef1c74db7e7a9fea2c0eb269d61e3b38e450a22e754941ac78479d6c54e1faf6037881d"

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

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

fmt.Printf("Calculated key: %x\n", publicKey)
fmt.Printf("Expected key:   %s\n", expectedPublicKey)
keyMatches := expectedPublicKey == hex.EncodeToString(publicKey)
fmt.Printf("Public key matches expected: %v\n", keyMatches)

buffer := []byte("4:salt6:foobar3:seqi1e1:v12:Hello World!")
calculatedSig := sign(privateKey, publicKey, buffer)

fmt.Printf("Calculated sig: %x\n", calculatedSig)
fmt.Printf("Expected sig:   %s\n", expectedSig)
sigMatches := expectedSig == hex.EncodeToString(calculatedSig)
fmt.Printf("Signature matches expected: %v\n", sigMatches)</code>

Dengan menyepadukan tersuai ini berfungsi ke dalam kod anda, anda boleh mengendalikan vektor ujian yang ditakrifkan dalam format kunci persendirian alternatif dan melaksanakan operasi seperti penjanaan dan tandatangan kunci awam tanpa menemui hasil yang tidak sepadan.

Atas ialah kandungan terperinci Mengapakah pelaksanaan Go ed25519 menjana kunci awam yang berbeza daripada yang dijangkakan dalam kes tertentu?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn