Go: Verify Cryptographic Signatures

Recently, I was implementing a webhook for Travis CI in Go. When a build finishes (depending on the settings), Travis POSTs to a previously specified URL. That requires the URL of the webhook to be publicly accessible (you can still Travis-encrypt the URL, but that’s just security-by-obscurity).

To give you the possibility to verify the POST query actually came from Travis, they not only send the payload but also a signature (as an HTTP header).

The BEGIN PUBLIC KEY and END PUBLIC KEY sections as well as the line breaks are just for human convenience, they don’t carry and data. However, they show that this public key is encoded in PEM format (like a lot of X.509 certificates).

Note: You might not need this step, but you need to at least convert your signature string into a byte array.

Now we have the public key and signature (stored in the correct format), let’s verify the signature of the message.

We start by hashing the message. This needs to be done with the same Hash algorithm that was used to create the signature. In my case it’s SHA-1, therefore I’m using the Sum function from the crypto/sha1 package:

import "crypto/sha1"
hash := sha1.Sum(message)

Unfortunately, all packages implementing the PublicKey interface (rsa, dsa and ecdsa, as mentioned above) feature a verifying function, but they have different names and (function) signatures:

The VerifyPKCS1v15 function expects four input parameters: the public key (in a public key interface), the type of hashed used (here crypto.SHA1), the complete hash (hash[:]) and the signature stored in a byte array.

If the function returns nil the message was successfully verified, otherwise the signature is invalid or there was some other kind of error.