验证Go中负载的签名

huangapple go评论75阅读模式
英文:

Verifying signature of payload in Go

问题

我正在验证数据发送者的身份。我获得了以PEM格式提供的RSA公钥,并且我知道数据经过了SHA256哈希函数的处理。在node.js平台上,可以进行等效的验证:

Ticket.prototype.verify = function (ticket) {
    if (!ticket) return null;

    var pubkey = fs.readFileSync('/etc/SCAMP/auth/ticket_verify_public_key.pem');

    var parts = ticket.split(',');

    if (parts[0] != '1') return null;

    var sig = new Buffer(parts.pop().replace(/-/g,'+').replace(/_/g,'/'), 'base64');

    var valid = crypto.createVerify('sha256').update( new Buffer(parts.join(',')) ).verify( pubkey, sig )
}

可以验证以下内容:

1,3063,21,1438783424,660,1+20+31+32+34+35+36+37+38+39+40+41+42+43+44+46+47+48+50+53+56+59+60+61+62+67+68+69+70+71+75+76+80+81+82+86+87+88+102+104+105+107+109+110+122+124,PcFNyWjoz_iiVMgEe8I3IBfzSlUcqUGtsuN7536PTiBW7KDovIqCaSi_8nZWcj-j1dfbQRA8mftwYUWMhhZ4DD78-BH8MovNVucbmTmf2Wzbx9bsI-dmUADY5Q2ol4qDXG4YQJeyZ6f6F9s_1uxHTH456QcsfNxFWh18ygo5_DVmQQSXCHN7EXM5M-u2DSol9MSROeBolYnHZyE093LgQ2veWQREbrwg5Fcp2VZ6VqIC7yu6f_xYHEvU0-ZsSSRMAMUmhLNhmFM4KDjl8blVgC134z7XfCTDDjCDiynSL6b-D-

通过在最后一个,处进行分割。分割的左侧是我关心的票据数据,右侧是我需要验证的签名,只有在验证签名之后,我才能使用票据数据。

我尝试将逻辑转换为Go语言:

func TestSigVerification(t *testing.T) {
    block, _ := pem.Decode(signingPubKey)
    if block == nil {
        t.Errorf("expected to block to be non-nil CERTIFICATE", block)
    }

    key, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        t.Errorf("could not parse PKIXPublicKey: `%s`", key)
    }

    rsaPubKey, ok := key.(*rsa.PublicKey)
    if !ok {
        t.Errorf("couldn't cast to rsa.PublicKey!")
    }

    ticket,_ := ParseTicketBytes(fullTicketBytes)

    h := sha256.New()
    h.Write(ticketBytes)
    digest := h.Sum(nil)

    err = rsa.VerifyPKCS1v15(rsaPubKey, crypto.SHA256, digest, ticket.Signature)
    if err != nil {
        t.Errorf("could not verify ticket: `%s` (digest: `%v`)", err, digest )
    }
}

但我相当确定VerifyPKCS1v15不等同于node.js的crypto.createVerify,因此这个测试用例会失败。我应该使用什么?如何使用公钥解密签名并获取SHA256?一旦我获得了解密后的SHA256值,我可以与我生成的SHA256进行基本比较。

这是一个可运行的Playground示例:http://play.golang.org/p/COx2OG-AiA

英文:

I am verifying the identity of the sender of a piece of data. I am provided the RSA public key in a PEM format and I know the data is passed through the SHA256 hashing function. The equivalent verification on the node.js platform:

Ticket.prototype.verify = function (ticket) {
    if (!ticket) return null;

    var pubkey = fs.readFileSync('/etc/SCAMP/auth/ticket_verify_public_key.pem');

    var parts = ticket.split(',');

    if (parts[0] != '1') return null;

    var sig = new Buffer(parts.pop().replace(/-/g,'+').replace(/_/g,'/'), 'base64');

    var valid = crypto.createVerify('sha256').update( new Buffer(parts.join(',')) ).verify( pubkey, sig )

Which can verify:

1,3063,21,1438783424,660,1+20+31+32+34+35+36+37+38+39+40+41+42+43+44+46+47+48+50+53+56+59+60+61+62+67+68+69+70+71+75+76+80+81+82+86+87+88+102+104+105+107+109+110+122+124,PcFNyWjoz_iiVMgEe8I3IBfzSlUcqUGtsuN7536PTiBW7KDovIqCaSi_8nZWcj-j1dfbQRA8mftwYUWMhhZ4DD78-BH8MovNVucbmTmf2Wzbx9bsI-dmUADY5Q2ol4qDXG4YQJeyZ6f6F9s_1uxHTH456QcsfNxFWh18ygo5_DVmQQSXCHN7EXM5M-u2DSol9MSROeBolYnHZyE093LgQ2veWQREbrwg5Fcp2VZ6VqIC7yu6f_xYHEvU0-ZsSSRMAMUmhLNhmFM4KDjl8blVgC134z7XfCTDDjCDiynSL6b-D-

by splitting on the last ,. The left side of the split is the ticket data I care about, the right side is the signature which I need to verify before I can use the ticket data.

I have tried to port the logic to go:

func TestSigVerification(t *testing.T) {
	block, _ := pem.Decode(signingPubKey)
	if block == nil {
		t.Errorf("expected to block to be non-nil CERTIFICATE", block)
	}

	key, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		t.Errorf("could not parse PKIXPublicKey: `%s`", key)
	}

	rsaPubKey, ok := key.(*rsa.PublicKey)
	if !ok {
		t.Errorf("couldn't cast to rsa.PublicKey!")
	}

	ticket,_ := ParseTicketBytes(fullTicketBytes)

	h := sha256.New()
	h.Write(ticketBytes)
	digest := h.Sum(nil)

	err = rsa.VerifyPKCS1v15(rsaPubKey, crypto.SHA256, digest, ticket.Signature)
	if err != nil {
		t.Errorf("could not verify ticket: `%s` (digest: `%v`)", err, digest )
	}
}

But I'm pretty sure VerifyPKCS1v15 is not equivalent to node's crypto.createVerify and this test case fails. What should I be using? How can I use the public key to decrypt the signature and get the sha256? once I have the decrypted sha256 value I could just do a basic comparison with the sha256 I have generated.

Here's a runnable playground example: http://play.golang.org/p/COx2OG-AiA

答案1

得分: 3

尽管我无法使其工作,但我怀疑问题在于你需要将sig从base64转换为字节,通过base64编码。请参考这个例子:

http://play.golang.org/p/bzpD7Pa9mr(特别是23到28行,他们必须将sig从字节编码为base64字符串以打印它,然后将字节版本输入到sig检查中,表明你必须使用字节版本而不是base64字符串)

我在这篇帖子中偶然发现了这个例子:
https://stackoverflow.com/questions/20655702/signing-and-decoding-with-rsa-sha-in-go

我发现golang通常希望在字节编码中使用字节。我尝试将你的sig字符串从base64解码为字节,但即使在将“-”替换为“+”,将“_”替换为“/”之后,它仍然无法工作,原因我不知道:

http://play.golang.org/p/71IiV2z_t8

至少这似乎表明你的sig可能有问题?它是否无效的base64?我认为如果你能找到解决这个问题的方法,其他部分应该可以工作!

英文:

Though I couldn't get it to work, I suspect the issue is that you'll need to convert the sig from base64 into bytes via the base64 encoding. See this example here:

http://play.golang.org/p/bzpD7Pa9mr (especially lines 23 to 28, where they have to encode the sig from bytes to base64 string to print it, then feed the byte version into the sig check, indicating that you have to use the byte version and not base64 string)

Which I stumbled across on this post:
https://stackoverflow.com/questions/20655702/signing-and-decoding-with-rsa-sha-in-go

I've found that golang generally expects bytes everywhere in byte encoding. I tried to decode your sig string from base64 to bytes however, even after replacing the '-' with '+' and the '_' with '/' it still won't work, for reasons unknown to me:

http://play.golang.org/p/71IiV2z_t8

At the very least this seems to indicate that maybe your sig is bad? If it isn't valid base64? I think if you can find a way to solve this the rest should work!

答案2

得分: 1

我尝试运行了你的代码,看起来你的票据格式不正确。它的长度不够。你从哪里获取这个值的?

请再次检查一下票据,这可能足够让你继续进行。

英文:

I tried running your code and it doesn't look like your ticket is well formed. It's not long enough. Where did you get the value from?

Double check that ticket -- that may just be enough to get you going.

huangapple
  • 本文由 发表于 2015年8月14日 07:17:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/31999971.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定