xrl
xrl

Reputation: 2244

Verifying signature of payload in Go

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

Upvotes: 2

Views: 7496

Answers (2)

The Answer Dude
The Answer Dude

Reputation: 76

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.

Upvotes: 1

im_ferris
im_ferris

Reputation: 31

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: 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!

Upvotes: 3

Related Questions