這是由於不同的ed25519私鑰格式。 ed25519密鑰以32字節種子開始。該種子用SHA512散列產生64個字節(也翻轉了幾位)。這些字節的前32個字節用於生成公鑰(也是32個字節),最後32個字節用於生成簽名。
Golang私鑰格式是32字節的種子與32字節的公鑰結合在一起。您使用的Bittorrent文檔中的私鑰是散列的64字節結果(或者可能只有64個隨機字節與散列結果使用相同的方式)。
由於無法反轉散列,因此無法將Bittorrent鍵轉換爲Golang API可接受的格式。
您可以根據現有軟件包生成一個Golang庫版本。
以下代碼取決於內部軟件包golang.org/x/crypto/ed25519/internal/edwards25519
,因此如果您想使用它,您需要將該軟件包複製出來以便它可用於您的代碼。它也非常「粗糙和準備好」,我基本上只是複製了現有代碼所需的代碼塊,以使其工作。
請注意,公鑰和簽名格式是相同的,所以只要您不共享私鑰,您就不需要使用此代碼來獲得工作實現。如果你想檢查測試向量,你將只需要它。
首先生成一個私人的公鑰:
// 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[:]
}
下生成簽名:
// 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
}
最後,我們可以使用這兩個函數來演示測試向量:
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)
添加更多,我看着https://github.com/orlp/ed25519在https://github.com/orlp/ed25519/bl ob/master/src/keypair.c#L15它生成(我認爲)PBK,它的ge_p3_tobytes更復雜https://github.com/orlp/ed25519/blob/master/src/ge.c#L321 golang版本是https://github.com/golang/crypto/blob/master/ed25519/ed25519.go#L43 –