Permalink
Browse files

First commit with Pusher example working.

  • Loading branch information...
bennadel committed Aug 17, 2012
0 parents commit 63736dab9eb329104435a9108723fa4e48fa571d
Showing with 208 additions and 0 deletions.
  1. +13 −0 README.md
  2. +26 −0 examples/Application.cfc
  3. +34 −0 examples/pusher_authentication.cfm
  4. +135 −0 lib/Crypto.cfc
@@ -0,0 +1,13 @@
+
+# Crypto.cfc - Crypto / Security Methods For ColdFusion
+
+by Ben Nadel
+([www.bennadel.com](http://www.bennadel.com))
+
+[ColdFusion 10 introduced the hmac() function][1] for generating secure, hashed
+message authentication codes (HMAC). This function makes dealing with 3rd-Party
+APIs much easier. Before ColdFusion 10, however, you would need to dip down into
+the Java layer to access the security libraries. This ColdFusion component -
+Crypto.cfc - attempts to make access to such libraries easier and more concise.
+
+[1]: http://www.bennadel.com/blog/2339-ColdFusion-10-Beta-Generating-Hash-Based-Message-Authentication-Codes-With-Hmac-.htm
@@ -0,0 +1,26 @@
+<cfscript>
+
+component
+ output = "false"
+ hint = "I define the application setttings and event handlers."
+ {
+
+
+ // Define the application settings.
+ this.name = hash( getCurrentTemplatePath() );
+ this.applicationTimeout = createTimeSpan( 0, 0, 1, 0 );
+ this.sessionManagement = false;
+
+ // Get the examples (current) directory
+ this.examplesDirectory = getDirectoryFromPath( getCurrentTemplatePath() );
+
+ // Get the root directory for our project.
+ this.projectDirectory = (this.examplesDirectory & "../");
+
+ // Map the Lib directory so we can instantiate our project components.
+ this.mappings[ "/lib" ] = (this.projectDirectory & "lib/");
+
+
+}
+
+</cfscript>
@@ -0,0 +1,34 @@
+<!---
+
+ Pusher App Message Authentication
+
+ This example is taken from : https://gist.github.com/376898
+
+--->
+
+<cfoutput>
+
+ <h1>
+ Pusher App REST API Auth Signature
+ </h1>
+
+ <cfset crypto = new lib.Crypto() />
+
+ <cfset key = "7ad3773142a6692b25b8" />
+
+ <cfset input = "POST\n/apps/3/channels/test_channel/events\nauth_key=278d425bdf160c739803&auth_timestamp=1272044395&auth_version=1.0&body_md5=7b3d404f5cde4a0b9b8fb4789a0098cb&name=foo" />
+
+ <!---
+ Replace with real new-line characters since ColdFusion doesn't recognize them
+ as embedded string character.
+ --->
+ <cfset input = replace( input, "\n", chr( 10 ), "all" ) />
+
+
+ <!--- Our value. --->
+ #crypto.hmacSha256( key, input )#<br />
+
+ <!--- Expected value. --->
+ 309fc4be20f04e53e011b00744642d3fe66c2c7c5686f35ed6cd2af6f202e445
+
+</cfoutput>
@@ -0,0 +1,135 @@
+<cfscript>
+
+component
+ output = "false"
+ hint = "I provide easy access to Java's HMAC security / crypto methods."
+ {
+
+
+ // I return an initialized component.
+ function init(){
+
+ // Store the MAC class definition so that its static methods can be accessed quickly.
+ variables.macClass = createObject( "java", "javax.crypto.Mac" );
+
+ // Return this object reference.
+ return( this );
+
+ }
+
+
+ // ---
+ // PUBLIC METHODS
+ // ---
+
+
+ // I hash the given input using the Sha-256 encoding algorithm and the given secret key. By
+ // default, the hash is returned as a HEX-encoded string.
+ function hmacSha256(
+ String key,
+ String input,
+ String encoding = "hex"
+ ){
+
+ // Hash the input using Hmac Sha-256.
+ var authenticationCode = this._hashInputWithAlgorithmAndKey( "HmacSHA256", key, input );
+
+ // Return the authentication code in the appropriate encoding.
+ return(
+ this._encodeByteArray( authenticationCode, encoding )
+ );
+
+ }
+
+
+ // ---
+ // PRIVATE METHODS
+ // ---
+
+
+ // I encode the byte array / binary value using the given encoding. The Hex-encoding is used
+ // by default.
+ function _encodeByteArray(
+ Any bytes,
+ String encoding = "hex"
+ ){
+
+ // Normalize the encoding value.
+ encoding = lcase( encoding );
+
+ // Checking encoding algorithm.
+ if (encoding == "hex"){
+
+ return(
+ lcase( binaryEncode( bytes, "hex" ) )
+ );
+
+ } else if (encoding == "base64"){
+
+ return(
+ binaryEncode( bytes, "base64" )
+ );
+
+ } else if (encoding == "binary"){
+
+ // No further encoding required.
+ return( bytes );
+
+ }
+
+ // If we made it this far, the encoding was not recognized or is not yet supported.
+ throw(
+ type = "InvalidEncoding",
+ message = "The requested encoding method [#encoding#] is not yet supported."
+ );
+
+ }
+
+
+ // I return a MAC generator for the given key and algorithm.
+ function _getMacInstance( String algorithm, String key ){
+
+ // Create the specification for our secret key.
+ var secretkeySpec = createObject( "java", "javax.crypto.spec.SecretKeySpec" ).init(
+ toBinary( toBase64( key ) ),
+ javaCast( "string", algorithm )
+ );
+
+ // Get an instance of our MAC generator for the given hashing algorithm.
+ var mac = variables.macClass.getInstance(
+ javaCast( "string", algorithm )
+ );
+
+ // Initialize the Mac with our secret key spec.
+ mac.init( secretkeySpec );
+
+ // Return the initialized Mac generator.
+ return( mac );
+
+ }
+
+
+ // I provide a generic method for creating an Hmac with various algorithms. The hash value
+ // is returned as a binary value / byte array.
+ function _hashInputWithAlgorithmAndKey(
+ String algorithm,
+ String key,
+ String input
+ ){
+
+ // Create our MAC generator.
+ var mac = this._getMacInstance( algorithm, key );
+
+ // Hash the input.
+ var hashedBytes = mac.doFinal(
+ toBinary( toBase64( input ) )
+ );
+
+ return( hashedBytes );
+
+ }
+
+
+}
+
+</cfscript>

0 comments on commit 63736da

Please sign in to comment.