go中无法验证SHA256签名
Unable to verify SHA256 signature in go
我一直在尝试使用 go crypto 包验证在 Node 中生成的签名。签名是从 createSig()
函数生成的。然后我正在用 verifySig()
验证它,但它总是失败。这些 private/public 密钥可以安全共享,因为它们是为此示例生成的。我能够 运行 从签名中在 Node 中进行验证而没有问题,但我不确定 go 中发生了什么导致它失败。
正在节点中生成签名
function createSig() {
const crypto = require("crypto");
function fromBase64(base64) {
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
}
const PRIVATE_KEY =
"-----BEGIN PRIVATE KEY-----\nMIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAyX1juQ2AVhS5NdKl\nJL5g4A+fPLUUWh2Tq1+f0Z1rb1dpCZ+RXECJAdW4ocsl5n24QtmzD66Z/s1bs+B5\nOyD4KwIDAQABAkBqxbiXsrDkbNzsybBbtUsO0Rh4Chk729qKAQVnBf2NpRmz3KAf\nMXP5M9Wr9HlD1PT8WUUaYvGtabbbkXTFq+pBAiEA+T2Lja3seY2NUxsR0Qi211Ug\nKCd820+5Tjft1XMf1aECIQDO9FDm5asV3q60YvqpifSawiS2JH/DS7Whg4X0M64i\nSwIhAPaKTY/g+eim/6O0RCRspUhNeRifLt9VdiyMIGOilFvhAiAJxgH4FYqR2tVX\nUYFS9l/l2xtOusSJ3Y5zVTnDQZmMpwIhAMibeam8MvHMr3FjTqE5CwOgsg6zXiWZ\nFA9ZnEINP5jz\n-----END PRIVATE KEY-----";
var message = "test";
var signer = crypto.createSign("RSA-SHA256");
signer.update(message);
return fromBase64(signer.sign(PRIVATE_KEY, "base64"));
}
正在验证中
func verifySig(message, signature string) (bool, error) {
var key = "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMl9Y7kNgFYUuTXSpSS+YOAPnzy1FFod\nk6tfn9Gda29XaQmfkVxAiQHVuKHLJeZ9uELZsw+umf7NW7PgeTsg+CsCAwEAAQ==\n-----END PUBLIC KEY-----"
block, _ := pem.Decode([]byte(key))
if block == nil {
return false, errors.New("uh oh")
}
sh := crypto.SHA256.New()
sh.Write([]byte(message))
hashed := sh.Sum(nil)
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return false, err
}
if pubKey, ok := pub.(*rsa.PublicKey); ok {
err := rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, hashed, []byte(signature))
if err != nil {
// THIS IS WHERE I END UP EVERY TIME
return false, err
}
return true, nil
}
}
工作节点验证:
function verifySig(message, signature) {
const PUBLIC_KEY =
"-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMl9Y7kNgFYUuTXSpSS+YOAPnzy1FFod\nk6tfn9Gda29XaQmfkVxAiQHVuKHLJeZ9uELZsw+umf7NW7PgeTsg+CsCAwEAAQ==\n-----END PUBLIC KEY-----";
var verifier = crypto.createVerify("RSA-SHA256");
verifier.update(message);
// will return true
return verifier.verify(PUBLIC_KEY, signature, "base64");
}
我认为您的代码有 2 个问题。
首先:在 NodeJs 中,您使用 Base64 对签名进行了编码,其次,您将 Base64 字符串转换为“Url Safe" Base64编码的字符串。
这两个步骤需要反过来(我不知道Go是否有内置的“Url-safe Base64解码功能”),然后才能使用签名字符串作为输入进行验证去吧
我一直在尝试使用 go crypto 包验证在 Node 中生成的签名。签名是从 createSig()
函数生成的。然后我正在用 verifySig()
验证它,但它总是失败。这些 private/public 密钥可以安全共享,因为它们是为此示例生成的。我能够 运行 从签名中在 Node 中进行验证而没有问题,但我不确定 go 中发生了什么导致它失败。
正在节点中生成签名
function createSig() {
const crypto = require("crypto");
function fromBase64(base64) {
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
}
const PRIVATE_KEY =
"-----BEGIN PRIVATE KEY-----\nMIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAyX1juQ2AVhS5NdKl\nJL5g4A+fPLUUWh2Tq1+f0Z1rb1dpCZ+RXECJAdW4ocsl5n24QtmzD66Z/s1bs+B5\nOyD4KwIDAQABAkBqxbiXsrDkbNzsybBbtUsO0Rh4Chk729qKAQVnBf2NpRmz3KAf\nMXP5M9Wr9HlD1PT8WUUaYvGtabbbkXTFq+pBAiEA+T2Lja3seY2NUxsR0Qi211Ug\nKCd820+5Tjft1XMf1aECIQDO9FDm5asV3q60YvqpifSawiS2JH/DS7Whg4X0M64i\nSwIhAPaKTY/g+eim/6O0RCRspUhNeRifLt9VdiyMIGOilFvhAiAJxgH4FYqR2tVX\nUYFS9l/l2xtOusSJ3Y5zVTnDQZmMpwIhAMibeam8MvHMr3FjTqE5CwOgsg6zXiWZ\nFA9ZnEINP5jz\n-----END PRIVATE KEY-----";
var message = "test";
var signer = crypto.createSign("RSA-SHA256");
signer.update(message);
return fromBase64(signer.sign(PRIVATE_KEY, "base64"));
}
正在验证中
func verifySig(message, signature string) (bool, error) {
var key = "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMl9Y7kNgFYUuTXSpSS+YOAPnzy1FFod\nk6tfn9Gda29XaQmfkVxAiQHVuKHLJeZ9uELZsw+umf7NW7PgeTsg+CsCAwEAAQ==\n-----END PUBLIC KEY-----"
block, _ := pem.Decode([]byte(key))
if block == nil {
return false, errors.New("uh oh")
}
sh := crypto.SHA256.New()
sh.Write([]byte(message))
hashed := sh.Sum(nil)
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return false, err
}
if pubKey, ok := pub.(*rsa.PublicKey); ok {
err := rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, hashed, []byte(signature))
if err != nil {
// THIS IS WHERE I END UP EVERY TIME
return false, err
}
return true, nil
}
}
工作节点验证:
function verifySig(message, signature) {
const PUBLIC_KEY =
"-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMl9Y7kNgFYUuTXSpSS+YOAPnzy1FFod\nk6tfn9Gda29XaQmfkVxAiQHVuKHLJeZ9uELZsw+umf7NW7PgeTsg+CsCAwEAAQ==\n-----END PUBLIC KEY-----";
var verifier = crypto.createVerify("RSA-SHA256");
verifier.update(message);
// will return true
return verifier.verify(PUBLIC_KEY, signature, "base64");
}
我认为您的代码有 2 个问题。
首先:在 NodeJs 中,您使用 Base64 对签名进行了编码,其次,您将 Base64 字符串转换为“Url Safe" Base64编码的字符串。
这两个步骤需要反过来(我不知道Go是否有内置的“Url-safe Base64解码功能”),然后才能使用签名字符串作为输入进行验证去吧