go - 为什么我用 openssl 和 golang 生成的 RSA 签名不同?

标签 go openssl rsa sign

我使用openssl命令对消息“Test.”进行签名,使用hexdump输出

# echo "Test." | openssl rsautl -inkey privite.key -sign -hexdump
0000 - 09 1b ce e2 4b 69 86 be-d7 b1 fb f0 ec e4 53 0e   ....Ki........S.
0010 - ef 9c a4 7b db d3 21 d5-3e 78 23 61 89 34 7e bc   ...{..!.>x#a.4~.
0020 - e9 1e 5a e9 f4 40 e6 53-07 e4 dd 1a fe 31 ec 42   ..Z..@.S.....1.B
0030 - 98 a5 07 d4 7e d9 f4 01-2f ba a3 65 18 b7 69 a4   ....~.../..e..i. 

十六进制字符串是091bcee24b69...

我的私钥

# cat private.Key
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
-----END RSA PRIVATE KEY-----

使用Golang生成签名

var prvKeyPem = `-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
-----END RSA PRIVATE KEY-----`

func GenerateSignature() {
    block, _ := pem.Decode([]byte(prvKeyPem))
    if block == nil {
        panic("failed to parse root certificate PEM")
    }
    privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) //x509.ParseCertificate(block.Bytes)
    if err != nil {
        panic("failed to parse certificate: " + err.Error())
    }
    indata := "Test."
    h := sha256.New()
    h.Write([]byte(indata))
    digest := h.Sum(nil)

    s, err := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA256, digest)
    if err != nil {
        panic("failed to sign:" + err.Error())
    }
    fmt.Printf("%x\n", s)
}

func main() {
    GenerateSignature()
}

运行这段代码,输出如下: 52e1cce3810c1a89693cf6965d1035618820a9e3a7b95203d885c4153dc3f7424b98e3ba628a186f1074d672bb59a1c0788a9c2064951ca2326eb1bf8e3e49e9

但我认为应该是:

091bcee24b69...

我哪里错了?谢谢

最佳答案

除了helmbert’s answer中描述的echo添加的换行符,OpenSSL rsautl 命令直接对提供的数据进行操作,而 Go 代码首先使用 SHA256 对数据进行哈希处理,然后对生成的摘要进行签名。

要使用 OpenSSL 执行与 Go 代码相同的操作,您可以使用 dgst command使用 -sign 选项(请注意,我在此处也将 -n 选项包含在 echo 中):

$ echo -n "Test." | openssl dgst -sha256 -sign private.key -hex
52e1cce3810c1a89693cf6965d1035618820a9e3a7b95203d885c4153dc3f7424b98e3ba628a186f1074d672bb59a1c0788a9c2064951ca2326eb1bf8e3e49e9

要采用另一种方式并在 Go 代码中不使用哈希对原始消息进行签名,您可以将 0 作为 hash 参数的值传递给 rsa.SignPKCS1v15。 :

indata := []byte("Test.")

s, err := rsa.SignPKCS1v15(nil, privKey, 0, indata)

关于go - 为什么我用 openssl 和 golang 生成的 RSA 签名不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37202268/

相关文章:

variables - 仅当条件为真时,如何在 go 中创建变量?

php - 找不到 CentOS OpenSSL php_openssl.dll

c# - TypeInitializationException 使用 OpenSsl.net

java - RSA加密: Java code to PHP code

使用 crypto/ssh 的 golang scp 文件

go - 使用 Truetype 对齐 golang 中的文本

php - Linux 服务器上的 OpenSSL 目录正常 - Windows XAMPP 上不行

ssh - 无法通过集市 ssh 到启动板

java - java中使用RSA对加密消息进行加密

angular - 在预检请求中发送自定义 header OPTIONS angular 5