ed25519 公鑰產生差異
ed25519 加密封包提供了一種從私鑰產生公鑰的方法。然而,使用者發現 Go 實作產生的公鑰與特定用例中的預期值不一致。
根本原因:
這種差異產生於用於表示 ed25519 私鑰的不同格式。 Go 套件使用一種格式,其中私鑰表示為 32 位元組種子和 32 個位元組公鑰的串聯。相反,定義預期結果的測試向量將私鑰表示為散列種子的 64 位元組輸出。
解決方案:
鑑於這是不可行的逆向雜湊過程,不可能將測試向量私鑰轉換為與 Go 實作相容的格式。或者,您可以建立支援替代私鑰格式的 Go 函式庫的修改版本。
修改後的函式庫程式碼:
以下程式碼片段提供了自訂版本Go 實作支援備用私鑰格式:
產生公鑰匙:
<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(&A, &hBytes) var publicKeyBytes [32]byte A.ToBytes(&publicKeyBytes) return publicKeyBytes[:] }</code>
簽章:
<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(&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">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>
透過整合這些自訂函數函數到您的程式碼中,您可以處理以替代私鑰格式定義的測試向量並執行公鑰生成和簽名等操作,而不會遇到不匹配的結果。
以上是為什麼 ed25519 的 Go 實作在某些情況下產生的公鑰與預期不同?的詳細內容。更多資訊請關注PHP中文網其他相關文章!