将 rsa.PublicKey 转换为 ssh.PublicKey

Converting rsa.PublicKey to ssh.PublicKey

我有一个 rsa.PublicKey,它由结构中的模数和 public 指数组成。我想验证一个用那个密钥签名的 ssh.Signature,我想如果我有一个 ssh.PublicKey 我可以在那个接口上调用 Verify 方法。但是,我找不到任何实现 ssh.PublicKey 并支持从 rsa.PublicKey 转换的 classes。我是否需要编写专有方法来执行此操作,或者是否有一些 class 我没有找到,或者有更好的方法来解决我的问题?

对于上下文,我从一个 x509.Certificate 中得到了 rsa.PublicKey,它来自一个 yubikey,在它的一个 PIV 插槽中证明了一个密钥。

crypto/ssh 包 http://godoc.org/golang.org/x/crypto/ssh#NewPublicKey can take an *rsa.PublicKey as parameter and returns an instance of the PublicKey interface that includes a Verify method (Verify(data []byte, sig *Signature) error) - http://godoc.org/golang.org/x/crypto/ssh#PublicKey 中的 NewPublicKey 函数。

下面的程序说明了这一点——我们创建一个新的 *rsa.PrivateKey 并用它签署一条消息,然后使用 NewPublicKey 函数将 *rsa.PublicKey 转换为 ssh.PublicKey 并验证签名;如果原始数据被修改,还要检查签名验证是否失败。为简洁起见省略了错误检查。

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "fmt"
    "log"

    "golang.org/x/crypto/ssh"
)

func main() {
    data := []byte("Hello, world!")

    // create a new key as *rsa.PrivateKey
    priv, _ := rsa.GenerateKey(rand.Reader, 512)
    signer, _ := ssh.NewSignerFromKey(priv)
    sig, _ := signer.Sign(rand.Reader, data)

    // extract the ssh.PublicKey from *rsa.PublicKey to verify the signature
    pub, _ := ssh.NewPublicKey(&priv.PublicKey)
    if err := pub.Verify(data, sig); err != nil {
        log.Fatalf("publicKey.Verify failed: %v", err)
    }
    fmt.Printf("Signature OK\n")
    // modify the data and make sure we get a failure
    data[0]++
    if err := pub.Verify(data, sig); err == nil {
        log.Printf("publicKey.Verify passed on bad data/signature, expect failure")
    }
}

输出:

Signature OK