Skip to content

Instantly share code, notes, and snippets.

@cflove
Created February 5, 2013 18:02
Show Gist options
  • Save cflove/4716338 to your computer and use it in GitHub Desktop.
Save cflove/4716338 to your computer and use it in GitHub Desktop.
Amazon AWS API URL Signature creation with ColdFusion
<cffunction name="awsurl" returntype="string" access="public" output="No">
<cfargument name="Query" type="string" required="true" />
<cfargument name="AWSAccessKeyId" type="string" required="true" />
<cfargument name="SecretKey" type="string" required="true" />
<cfargument name="Host" type="string" default="ec2.amazonaws.com" />
<cfargument name="Methord" type="string" default="GET" />
<cfargument name="URI" type="string" default="/" />
<cfargument name="SignatureVersion" type="string" default="2" />
<cfargument name="Version" type="date" default="2012-04-01" />
<cfargument name="http" type="string" default="https" hint="https|http" />
<!--- add common values --->
<cfset local.Time = dateConvert("local2Utc",now())>
<cfset local.Time = "#DateFormat(local.Time,'yyyy-mm-dd')#T#TimeFormat(local.Time,'HH:mm:ss')#">
<cfset arguments.Query = "#arguments.Query#&Timestamp=#local.Time#&SignatureVersion=#arguments.SignatureVersion#&Version=#arguments.Version#&SignatureMethod=HmacSHA256">
<!--- sort QueryString --->
<cfset arguments.Query = ListToArray(arguments.Query,'&')>
<cfset ArraySort(arguments.Query,'text')>
<!--- prepend AccessKeyID --->
<cfset ArrayPrepend(arguments.Query, "AWSAccessKeyId=#arguments.AWSAccessKeyId#")>
<!--- url encode each values --->
<cfset local.SortedString = ArrayNew(1)>
<cfloop from="1" to="#ArrayLen(arguments.Query)#" index="local.i">
<cfset local.value = arguments.Query[local.i]>
<cfif listlen(local.value,'=') gt 1>
<cfset ArrayAppend(local.SortedString,"#listfirst(local.value,'=')#=#reservedEncod(listlast(local.value,'='))#")>
<cfelse>
<cfset ArrayAppend(local.SortedString,"#local.value#")>
</cfif>
</cfloop>
<!--- create signature string --->
<cfset local.toEncode = "#arguments.Methord##chr(10)##arguments.Host##chr(10)##arguments.URI##chr(10)##ArrayToList(local.SortedString,'&')#">
<cfoutput><pre>#local.toEncode#</pre></cfoutput>
<!--- encode Signature String --->
<cfset local.Signature = URLEncodedFormat(ToBase64(HMAC_SHA256(local.toEncode,arguments.SecretKey)))>
<cfset arguments.Query = ArrayToList(arguments.Query,'&')>
<cfset arguments.Query = "#arguments.http#://#arguments.Host##arguments.URI#?#arguments.Query#&Signature=#local.Signature#">
<cfreturn arguments.Query>
</cffunction>
<cffunction name="reservedEncod" returntype="string" access="public" output="no">
<cfargument name="string" type="string" required="true" />
<cfset local.reserved = "!|##|$|&|'|(|)|*|+|,|/|:|;|=|?|@|[|]| ">
<cfloop list="#local.reserved#" index="local.i" delimiters="|">
<cfif find(local.i,arguments.string)>
<cfset arguments.string = replace(arguments.string,local.i, "%#ucase(FormatBaseN(Asc(local.i),'16'))#", 'all')>
</cfif>
</cfloop>
<cfreturn arguments.string>
</cffunction>
<cffunction name="HMAC_SHA256" returntype="binary" access="public" output="no">
<cfargument name="signMessage" type="string" required="true" />
<cfargument name="signKey" type="string" required="true" />
<cfset local.jMsg = JavaCast("string",arguments.signMessage).getBytes("iso-8859-1") />
<cfset local.jKey = JavaCast("string",arguments.signKey).getBytes("iso-8859-1") />
<cfset local.key = createObject("java","javax.crypto.spec.SecretKeySpec") />
<cfset local.mac = createObject("java","javax.crypto.Mac") />
<cfset local.key = local.key.init(local.jKey,"HmacSHA256") />
<cfset local.mac = local.mac.getInstance(local.key.getAlgorithm()) />
<cfset local.mac.init(local.key) />
<cfset local.mac.update(local.jMsg) />
<cfreturn local.mac.doFinal() />
</cffunction>
@surgiie
Copy link

surgiie commented Jan 30, 2017

I cant seem to get HMAC_SHA256 function to generate the proper signature according to the response from amazon. Do you have an updated solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment