Maison >développement back-end >Golang >Pourquoi l'implémentation Go de ed25519 génère-t-elle une clé publique différente de celle attendue dans certains cas ?

Pourquoi l'implémentation Go de ed25519 génère-t-elle une clé publique différente de celle attendue dans certains cas ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-10-30 17:24:031085parcourir

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

Disparité de génération de clé publique ed25519

Le package cryptographique ed25519 fournit un moyen de générer des clés publiques à partir de clés privées. Cependant, les utilisateurs ont observé que la clé publique générée par l'implémentation Go ne correspond pas à la valeur attendue dans des cas d'utilisation spécifiques.

Cause fondamentale :

Cette disparité découle des différents formats utilisés pour représenter les clés privées ed25519. Le package Go utilise un format dans lequel la clé privée est représentée comme la concaténation de la graine de 32 octets et de la clé publique de 32 octets. À l'inverse, les vecteurs de test définissant les résultats attendus représentent la clé privée comme résultat de 64 octets du hachage de la graine.

Solution :

Étant donné qu'il n'est pas possible de inverser le processus de hachage, il est impossible de convertir les clés privées du vecteur de test dans un format compatible avec l'implémentation Go. Vous pouvez également créer une version modifiée de la bibliothèque Go qui prend en charge le format de clé privée alternative.

Code de bibliothèque modifié :

Les extraits de code suivants fournissent une version personnalisée de l'implémentation Go pour prendre en charge le format de clé privée alternative :

Génération de la clé publique :

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

Signature :

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

Démonstration :

Le code suivant démontre l'utilisation des fonctions personnalisées pour générer la clé publique et la signature attendues :

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

En intégrant ces fonctions personnalisées fonctions dans votre code, vous pouvez gérer les vecteurs de test définis dans le format de clé privée alternative et effectuer des opérations telles que la génération et la signature de clé publique sans rencontrer de résultats incompatibles.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn