Thursday, January 24, 2013

Maps for Business: Generating Valid Signatures with Adobe ColdFusion 9


Google Maps API for Business customers need to generate a valid digital signature that needs to be passed as a URL parameter to invoke some of the web services, and Google Developers' YouTube channel has a video with step-by-step instructions on doing this in Python.

Detailed explanations on the 5 steps to generate a valid digital signature are documented on Google Developer site with examples in Python, C#, Java, etc., but not in Adobe ColdFusion: http://goo.gl/iYLPi

I recently had to help a Senior Developer generate a valid digital signature in Adobe ColdFusion 9 after watching the YouTube video above.  Please see the steps and code snippet below.

Note: You can easily convert this snippet into a User-defined Function that accepts the coordinates as the input parameters and returns the digital signature in modified Binary64, that is safe to be passed as a URL parameter.  Please make use of the function HMAC() that is available in Adobe ColdFusion 10 instead, if you're coding in ColdFusion 10: http://goo.gl/O1e2W


<cfscript>

//Step 1: Construct full URL to retrieve street view image.
google_mapapi_url = "http://maps.googleapis.com";
streetviewimage_endpoint = "/maps/api/streetview";
encodedParameters = 
'location=#URLEncodedFormat("38.909084,-77.036767")#&sensor=false&client=YOUR-CLIENT-ID-HERE';
full_url 
  = google_mapapi_url & streetviewimage_endpoint & "?" &encodedParameters;
     
//Step 2: Strip off the domain portion of the full URL.     
url_to_sign = streetviewimage_endpoint & "?" & encodedParameters;

//Step 3.1: Retrieve your private key.
privatekey = "YOUR-PRIVATE-CRYPTO-KEY-HERE";
     
//Step 3.2: Decode the private key from web-safe base 64 to binary.
privatekeyBase64 
   = Replace(Replace(privatekey,"-","+","all"),"_","/","all"); 
decodedKeyBinary = BinaryDecode(privatekeyBase64,"base64");

//Step 3.3: Sign the URL in Step 2 above using the HMAC-SHA1 algorithm.
// Get an HMAC-SHA1 signing key from the raw key bytes.
secretKeySpec = 
CreateObject("java","javax.crypto.spec.SecretKeySpec").init(
decodedKeyBinary,"HmacSHA1");
//Note: In ColdFusion 10, you can simply use HMAC() function.
Hmac 
 = CreateObject("java","javax.crypto.Mac").getInstance("HmacSHA1");

Hmac.init(secretKeySpec);

// Compute the binary signature for the request.     
encryptedBytes = Hmac.doFinal(toBinary(toBase64(url_to_sign)));

// Encode the binary signature in base 64.
signature = BinaryEncode(encryptedBytes, "base64");


//Step 4: Convert the signature into something that can be passed withihn a URL.
signatureModified = Replace(Replace(signature,"+","-","all"),"/","_","all");

//Step 5: Attach the signature to the URL parameter signature
streetimage_url =  full_url & "&signature=" & signatureModified;

</cfscript>