【问题标题】:How do I sign a curve25519 key in golang?如何在golang中签署curve25519密钥?
【发布时间】:2020-06-26 01:06:49
【问题描述】:

我正在尝试从 Signal in Go 中实现 X3DH 算法。但是,我在如何签署 Public Signed PreKey 上遇到了困难。

根据规范,它应该是 X25519 密钥。在查看 Github 上以前的实现时,他们从 curve25519 包中生成了一个 [32]byte 密钥,然后将其转换为一个 ed25519 密钥,然后对其进行签名。

但是,他们用于转换的软件包已被弃用 (github.com/agl/ed25519)。因此,我需要能够将密钥转换为ed25519,以便我可以使用当前的ed25519 包(golang.org/x/crypto/25519)对它们进行签名,或者为curve25519 密钥实现签名和验证功能。

【问题讨论】:

    标签: algorithm go cryptography ed25519 curve-25519


    【解决方案1】:

    Ed25519 键可以轻松转换为X25519 键,Ed25519 使用的扭曲 Edwards 曲线和X25519 使用的蒙哥马利曲线等效于 birationally

    爱德华兹曲线上的点通常称为 (x, y),而蒙哥马利曲线上的点通常称为 (u, v)。

    您不需要库来进行转换,它真的很简单......

    (u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)
    (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
    

    这是 Google 的 Golang 安全主管 Filippo Valsorda 的精彩 blog,他正在讨论这个话题。

    【讨论】:

    • 我之前确实看过那篇文章并遇到了问题。在文章中它指出:“应该提到在两条曲线之间转换密钥的先例:Signal 的 XEd25519。他们做的与我们想要做的相反,他们为 EdDSA 使用 X25519 密钥。附带一个问题:一个 X25519 公钥不带 v 坐标,所以它可以映射到两个 Ed25519 密钥。他们通过将 Edwards 点符号位定义为 0 来解决这个问题,然后否定 Edwards 秘密标量,如果它会生成一个正的点符号。”老实说:我不知道如何实现这一点。
    • 查看我在下面发布的答案。这是我最终能够做到的,但涉及使用“golang.org/x/crypto/ed25519/internal”中的代码。再说一次,老实说,我并不完全熟悉此转换过程的细节,非常感谢您的意见,因为我不清楚如何将上述内容放入代码中。
    • @Jadefox10200,你现在在哪里?你卡在哪一部分?这可能很棘手......
    • 虽然下面的函数似乎可以工作,但我实际上并不完全理解它在做什么。验证功能确实验证了签名,但由于我不明白它是如何做到这一点的,所以我不确定我是否正确地实现了这个过程。您的回答确实有帮助,并且我现在正在花时间学习以实际尝试了解它是如何工作的。我宁愿自己实现一些东西,而不是从内部库中“抄袭”代码。
    【解决方案2】:

    这会接收一个公共的curve25519 密钥并将其转换为一个ed25519 的公共密钥。我没有编写此代码,但似乎正在做上面伍德斯托克所说的事情。欢迎提供更多信息:

    func Verify(publicKey [32]byte, message []byte, signature *[64]byte) bool {
    
    publicKey[31] &= 0x7F
    
    /* Convert the Curve25519 public key into an Ed25519 public key.  In
    particular, convert Curve25519's "montgomery" x-coordinate into an
    Ed25519 "edwards" y-coordinate:
    ed_y = (mont_x - 1) / (mont_x + 1)
    NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp
    Then move the sign bit into the pubkey from the signature.
    */
    
    var edY, one, montX, montXMinusOne, montXPlusOne FieldElement
    FeFromBytes(&montX, &publicKey)
    FeOne(&one)
    FeSub(&montXMinusOne, &montX, &one)
    FeAdd(&montXPlusOne, &montX, &one)
    FeInvert(&montXPlusOne, &montXPlusOne)
    FeMul(&edY, &montXMinusOne, &montXPlusOne)
    
    var A_ed [32]byte
    FeToBytes(&A_ed, &edY)
    
    A_ed[31] |= signature[63] & 0x80
    signature[63] &= 0x7F
    
    var sig = make([]byte, 64)
    var aed = make([]byte, 32)
    
    copy(sig, signature[:])
    copy(aed, A_ed[:])
    
    return ed25519.Verify(aed, message, sig)
    

    这使用来自“golang.org/x/crypto/ed25519/internal”的函数

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      • 1970-01-01
      • 2020-03-06
      • 1970-01-01
      • 1970-01-01
      • 2019-01-12
      相关资源
      最近更新 更多