ed25519.公开结果不同

2024-04-15

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

这些数据来自http://www.bittorrent.org/beps/bep_0044.html http://www.bittorrent.org/beps/bep_0044.html:测试2(用盐可变)

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

代码在这里https://play.golang.org/p/UJNPCyuGQB 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)
}

如何使用 golang 生成与 bep 相同的公钥?


这是由于 ed25519 私钥格式不同造成的。 ed25519 密钥以 32 字节开始seed。该种子使用 SHA512 进行哈希处理,生成 64 字节(也有几个位被翻转)。其中前 32 个字节用于生成公钥(也是 32 个字节),后 32 个字节用于生成签名。

Golang 私钥格式是 32 字节种子与 32 字节公钥连接。您正在使用的 Bittorrent 文档中的私钥是哈希的 64 字节结果(或者可能只是与哈希结果使用相同方式的 64 随机字节)。

由于无法反转哈希值,因此您无法将 Bittorrent 密钥转换为 Golang API 可接受的格式。

您可以基于现有包生成 Golang lib 的版本。

以下代码依赖于内部包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)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ed25519.公开结果不同 的相关文章

随机推荐

  • 如何在linux中用c在文件中打洞以擦除数据

    更新 这个FALLOC FL PUNCH HOLE最初不支持3 0 0 17 我想我需要修补它 我知道linux有这个hole功能 我想知道是否可以在现有文件中打一个洞 具体来说 我创建了一个名为hole test通过这些代码 18 inc
  • UIAlertController 自定义字体在 iOS 上不起作用

    UIAlertController 自定义字体不起作用 下面的代码是一个函数ShowActionSheetAsync show ActionSheet 此时我想改变字体ActionSheet 我尝试了多种方法 但效果并不好 有好的解决办法吗
  • Unity项目没有解决方案文件

    我刚刚开始学习 Unity 并且创建了一个项目 但我的项目中没有包含 sln 文件 每次我创建 C 脚本并在 Xamarin Studio 中打开它时 我都无法获得任何智能感知 unity项目中没有sln文件正常吗 如果没有 如何将解决方案
  • 获取所有输入值 - Vuejs

    我有多个input简单 VueJs 应用程序中的元素 但我没有 和 表单元素 现在我想一次获取所有输入值并发送到服务器端 laravel 进行处理 div div
  • 如何拦截所有节点request-promise http请求来修改请求选项?

    我想创建一个global请求拦截器request promise基于请求 以便我可以添加x request id所有传出请求的标头 由于该行为在所有传出请求中都很常见 因此我不想在发出请求的任何地方添加此功能 我在库文档中没有注意到此类功能
  • 引用本地计算机上的 javascript 文件

    我知道可以像这样引用网络上的第三方 JavaScript 文件 是否可以通过执行类似的操作来引用本地计算机上的 javaScript 文件 我怀疑这可能是一个禁忌 因为它可能是网站找出客户端计算机上有哪些文件的一种方式 我想这样做的原因是因
  • python 对象可以有嵌套属性吗?

    我有一个定义如下的对象 class a property def prop self print hello from object prop property def prop1 self print Hello from object
  • .gitlab-ci.yml 中的规则条件是否有 AND 选项?

    我想创建一些嵌套条件 当它是合并或合并请求并且以特定名称启动 功能 时 我需要此管道才能工作 那么 作业的 唯一 选项中是否有 AND 条件 不 那里没有 你必须使用rules https docs gitlab com ee ci yam
  • 如何创建开始菜单快捷方式

    我正在构建一个自定义安装程序 如何在开始菜单中创建可执行文件的快捷方式 这是我到目前为止所想出的 string pathToExe C Program Files x86 TestApp TestApp exe string commonS
  • mysql 使用addslashes() [重复]

    这个问题在这里已经有答案了 可能的重复 mysql real escape string 能做什么 而addslashes 不能 https stackoverflow com questions 534742 what does mysq
  • 如何在 iOS 应用程序中使用 Berkeley DB?

    我想在 iOS 应用程序中使用 Berkeley DB 但我不知道如何去做 如何将 Berkeley DB 集成到 iOS 项目中 你如何通过 Objective C 与它通信 是否有任何教程或示例可以演示如何做到这一点 首先要注意的是 该
  • 是否可以在不使用 boto3 下载 S3 文件的情况下获取其内容?

    我正在研究一个从 a 中转储文件的过程Redshift数据库 并且不希望必须在本地下载文件来处理数据 我看到了Java has a StreamingObject类可以做我想要的事情 但我还没有看到类似的东西boto3 如果你有一个mybu
  • 模块“pandas”没有属性“rolling_mean”

    我正在尝试构建 ARIMA 用于异常检测 我需要找到时间序列图的移动平均值 我尝试为此使用 pandas 0 23 import pandas as pd import numpy as np from statsmodels tsa st
  • 地理编码器错误 java.io.IOException:无法解析来自服务器的响应

    Code Geocoder geocoder new Geocoder map this Locale getDefault List
  • 为什么sonar:sonar需要先安装mvn?

    官方文档http docs sonarqube org display SONAR Analyzing with Maven http docs sonarqube org display SONAR Analyzing with Mave
  • iOS:通过自定义 UITableViewCell 上的 UITextView 选择

    我有一个带有图像和 UITextView 属性的自定义 UITableViewCell 文本视图跨越到单元格的边缘 我的问题是点击文本视图未在 didSelectRowAtIndexPath 中注册 我怎样才能让我可以 点击 我的文本视图
  • Login-AzureRmAccount 命令无法从托管 C# 应用程序运行

    我正在使用 powershell 脚本登录到 azure 为此我编写了简单的命令 Login AzureRmAccount 并在单击按钮时将该脚本调用到 C 代码中 它在本地工作正常 但是当我在服务器上托管此页面时 身份验证弹出窗口未打开
  • 如何在 PHP 中打印今天的尼泊尔日期? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想以不同的日期格式回显打印尼泊尔日历日期 请看一下下面的代码 有一个 jquery 日期选择器 http sajanmaharjan c
  • 是否可以预加载和缓存视频文件而不将它们添加到 DOM?

    我正在开发一款游戏 根据得到的结果触发 30 个小视频文件中的一个 由于视频需要在用户交互后立即播放 因此理想情况下我希望预加载视频并准备好播放 我添加了 PreloadJS 对我需要的所有资源进行了排队 查看检查器中的 网络 选项卡 我可
  • ed25519.公开结果不同

    使用包https github com golang crypto tree master ed25519 https github com golang crypto tree master ed25519我正在尝试获取给定私钥的公钥 这