当前位置: 首页 > 知识库问答 >
问题:

ed25519。公众的结果是不同的

孙德宇
2023-03-14

使用软件包https://github.com/golang/crypto/tree/master/ed25519我正在尝试获取给定私钥的公钥。

这些数据来自http://www.bittorrent.org/beps/bep_0044.html:试验2(可与盐发生变化)

问题是, ed25519.Public()不会返回相同的公钥,当我给它输入给定的私钥。Go语言实现返回PVK的最后32个字节。但在我的测试数据中,这是出乎意料的。

这里的代码https://play.golang.org/p/UJNPCyuGQB

package main

import (
    "encoding/hex"
    "golang.org/x/crypto/ed25519"
    "log"
)

func main() {
    priv := "e06d3183d14159228433ed599221b80bd0a5ce8352e4bdf0262f76786ef1c74db7e7a9fea2c0eb269d61e3b38e450a22e754941ac78479d6c54e1faf6037881d"
    pub := "77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548"
    sig := "6834284b6b24c3204eb2fea824d82f88883a3d95e8b4a21b8c0ded553d17d17ddf9a8a7104b1258f30bed3787e6cb896fca78c58f8e03b5f18f14951a87d9a08"
    // d := hex.EncodeToString([]byte(priv))
    privb, _ := hex.DecodeString(priv)
    pvk := ed25519.PrivateKey(privb)
    buffer := []byte("4:salt6:foobar3:seqi1e1:v12:Hello World!")
    sigb := ed25519.Sign(pvk, buffer)
    pubb, _ := hex.DecodeString(pub)
    sigb2, _ := hex.DecodeString(sig)
    log.Println(ed25519.Verify(pubb, buffer, sigb))
    log.Printf("%x\n", pvk.Public())
    log.Printf("%x\n", sigb)
    log.Printf("%x\n", sigb2)
}

如何使用Go语言生成与bep相同的公钥?

共有1个答案

柳和怡
2023-03-14

这是由于不同的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)
 类似资料:
  • 问题内容: 我很难理解scikit-learn和scikit-learn之间的区别(如果有)。 试图预测具有不平衡类的二进制输出(Y = 1时约为1.5%)。 分类器 大鹏曲线 AUC的 和 有人可以解释这种差异吗?我以为两者都只是在计算ROC曲线下的面积。可能是因为数据集不平衡,但我不知道为什么。 谢谢! 问题答案: AUC并不总是在ROC曲线的曲线下方。曲线下面积为下(抽象)地区 的一些 曲线

  • 这是我的代码: null

  • 我正在尝试更新一些代码,以使用Java 8的特性来解析多种日期格式。我机器上的本地时间设置为UTC-11。 以下代码在使用SimpleDateform时有效。 我正在尝试更新此代码,以使用Java 8中的DateTimeFormatter给出与上述相同的日期,以便我可以处理另一种日期格式。 [解决]我能够通过使用ZonedDateTime解决这个问题。 //更正日期是我想要的,星期三9月5日20:

  • 我为Aeron的演示做了一些基准测试,但我发现,如果我对相同的传输使用不同的工具,我得到的结果略有不同。 例如,如果我使用HDR直方图,我得到的结果与维护人员在测试中得到的数字一致: 我的代码https://github.com/easy-logic/transport-benchmarks/blob/master/aeron-ping/src/main/java/io/easylogic/ben

  • 我在这里漏掉了什么?我试过上/下现金,每个字节之间的空格。我不确定还能试什么。 这个问题开始是因为我在Python中实现了这个,但在我担心代码之前,我试图理解为什么这是不同的。

  • 我正在尝试使用ED25519和Go从私钥中提取公钥。 我将私钥字节值传递给我的方法,从中创建一个新的ed25519私钥结构,然后使用方法检索公钥。 它没有出错,但生成的公钥字节总是空的,在创建私钥结构时是否有错误?