One important task for connecting to the GoGrid API is calculating your signature. From their documentation, this is calculated by:
"generating an MD5 hash made up by concatenating the API key, the API user's shared secret, and a UNIX timestamp reflecting the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) when the request is made."
The keyword in this definition is: seconds since the Unix Epoch.
Unfortunately, I did not read this definition closely, and naively translated my already working Python implementation:
import md5 import time class GoGridClient: """sample gogrid api client""" api_key = 'xxxxxxxxxxx' secret = 'someonesSecret' .... def getSignature(self,key,secret): """ create sig from md5 of key + secret + time """ m = md5.new(key+secret+str(int(time.time()))) return m.hexdigest()
to the following Scala implementation, with a little help from Code Redefined's post for calculating the MD5 sum in Scala:
import java.security.MessageDigest object BrokenClient { val apiKey = "xxxxxxxxxxx" val apiSecret = "someonesSecret" val apiSignature: String = { // m = md5.new(key+secret+str(int(time.time()))) val signature = MessageDigest.getInstance("MD5") val timeStamp = System.currentTimeMillis().toString //<-- WRONG!!!! signature.update(apiKey.getBytes) signature.update(apiSecret.getBytes) signature.update(timeStamp.getBytes) signature.digest().map(0xFF & _).map { "%02x".format(_) }.foldLeft("") { _ + _ } } }
And sadly kept getting a 403: Authentication Failed error. The correct way to implement this is:
import java.security.MessageDigest object BrokenClient { val apiKey = "xxxxxxxxxxx" val apiSecret = "someonesSecret" val apiSignature: String = { // m = md5.new(key+secret+str(int(time.time()))) val signature = MessageDigest.getInstance("MD5") val timeStamp = ((java.util.Calendar.getInstance(TimeZone.getTimeZone("GMT-0:00")).getTimeInMillis()) / 1000).toString //<-- YAY ^_^ signature.update(apiKey.getBytes) signature.update(apiSecret.getBytes) signature.update(timeStamp.getBytes) signature.digest().map(0xFF & _).map { "%02x".format(_) }.foldLeft("") { _ + _ } } }
Note that there is some kinda weirdness going on, in that timeStamp works even if you don't pass in a time zone, or if you pass in a random time zone.
No comments:
Post a Comment