Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the New York ColdFusion User Group (Apr. 2008) with:

Converting Data Between String, Binary, Hex, And Base64 Format In ColdFusion

By Ben Nadel on
Tags: ColdFusion

The other day, when I was looking up test cases for my Crypto.cfc project, I came across some hex-encoded values that I needed to convert to plain "String" values before I could easily use them in my Unit Tests. After doing this, it occurred to me that it might be fun to wrap the ColdFusion functions, binaryEncode() and binaryDecode(), into smaller, one-liner functions for data-type conversion. What I came up with was the following one-liners:

  • base64ToHex()
  • base64ToString()
  • hexToBase64()
  • hexToString()
  • stringToBase64()
  • stringToBinary()
  • stringToHex()

I left out the following data type conversions because they can already be performed in ColdFusion using a single line of code:

  • base64ToBinary() :: binaryDecode( base64Value, "base64" )
  • binaryToBase64() :: binaryEncode( binaryValue, "base64" )
  • binaryToHex() :: binaryEncode( binaryValue, "hex" )
  • binaryToString() :: toString( binaryValue )
  • hexToBinary() :: binaryDecode( hexValue, "hex" )
  • stringToBase64() :: toBase64( stringValue )

I know that my use of the term, "string," is not so semantically correct. After all, my Hex and Base64 values are also strings. In this case, I am simply using the term "string" to denote a value that doesn't represent a hex or base64 binary-encoding.

It might be easier to just look at the functions:

  • <cfscript>
  •  
  •  
  • function base64ToHex( String base64Value ){
  •  
  • var binaryValue = binaryDecode( base64Value, "base64" );
  • var hexValue = binaryEncode( binaryValue, "hex" );
  •  
  • return( lcase( hexValue ) );
  •  
  • }
  •  
  •  
  • function base64ToString( String base64Value ){
  •  
  • var binaryValue = binaryDecode( base64Value, "base64" );
  • var stringValue = toString( binaryValue );
  •  
  • return( stringValue );
  •  
  • }
  •  
  •  
  • function hexToBase64( String hexValue ){
  •  
  • var binaryValue = binaryDecode( hexValue, "hex" );
  • var base64Value = binaryEncode( binaryValue, "base64" );
  •  
  • return( base64Value );
  •  
  • }
  •  
  •  
  • function hexToString( String hexValue ){
  •  
  • var binaryValue = binaryDecode( hexValue, "hex" );
  • var stringValue = toString( binaryValue );
  •  
  • return( stringValue );
  •  
  • }
  •  
  •  
  • function stringToBase64( String stringValue ){
  •  
  • var binaryValue = stringToBinary( stringValue );
  • var base64Value = binaryEncode( binaryValue, "base64" );
  •  
  • return( base64Value );
  •  
  • }
  •  
  •  
  • function stringToBinary( String stringValue ){
  •  
  • var base64Value = toBase64( stringValue );
  • var binaryValue = toBinary( base64Value );
  •  
  • return( binaryValue );
  •  
  • }
  •  
  •  
  • function stringToHex( String stringValue ){
  •  
  • var binaryValue = stringToBinary( stringValue );
  • var hexValue = binaryEncode( binaryValue, "hex" );
  •  
  • return( lcase( hexValue ) );
  •  
  • }
  •  
  •  
  • // ------------------------------------------------------ //
  • // ------------------------------------------------------ //
  • // ------------------------------------------------------ //
  • // ------------------------------------------------------ //
  •  
  •  
  •  
  • // Let's create a string value to test with.
  • message = "Danger zone!";
  •  
  • writeOutput( "Original :: " & message );
  • writeOutput( "<br />" );
  •  
  •  
  • // Now, let's check to the String-to-XXX conversions.
  • writeOutput( "<br />" );
  •  
  •  
  • messageAsHex = stringToHex( message );
  •  
  • writeOutput( "Hex :: " & messageAsHex );
  • writeOutput( "<br />" );
  •  
  • messageAsBase64 = stringToBase64( message );
  •  
  • writeOutput( "Base64 :: " & messageAsBase64 );
  • writeOutput( "<br />" );
  •  
  • messageAsBinary = stringToBinary( message );
  •  
  • writeOutput( "Binary :: [B" & arrayLen( messageAsBinary ) );
  • writeOutput( "<br />" );
  •  
  •  
  • // Now let's try converting back to string.
  • writeOutput( "<br />" );
  •  
  •  
  • hexToMessage = hexToString( messageAsHex );
  •  
  • writeOutput( "From Hex :: " & hexToMessage );
  • writeOutput( "<br />" );
  •  
  • base64ToMessage = base64ToString( messageAsBase64 );
  •  
  • writeOutput( "From Base64 :: " & base64ToMessage );
  • writeOutput( "<br />" );
  •  
  • binaryToMessage = toString( messageAsBinary );
  •  
  • writeOutput( "From Binary :: " & binaryToMessage );
  • writeOutput( "<br />" );
  •  
  •  
  • // Now let's just test the cross-encoding conversions.
  • writeOutput( "<br />" );
  •  
  •  
  • check = stringToHex( message );
  • check = hexToBase64( check );
  • check = base64ToString( check );
  •  
  • writeOutput( "Check 1 :: " & check );
  • writeOutput( "<br />" );
  •  
  • check = stringToBase64( message );
  • check = base64ToHex( check );
  • check = hexToString( check );
  •  
  • writeOutput( "Check 2 :: " & check );
  • writeOutput( "<br />" );
  •  
  •  
  • </cfscript>

As you can see, most of these make use of one or both of the binary encode/decode functions in ColdFusion. When we run the above code, we get the following page output:

Original :: Danger zone!

Hex :: 44616e676572207a6f6e6521
Base64 :: RGFuZ2VyIHpvbmUh
Binary :: [B12

From Hex :: Danger zone!
From Base64 :: Danger zone!
From Binary :: Danger zone!

Check 1 :: Danger zone!
Check 2 :: Danger zone!

Lana? Lana? Laaaaaaannaaaaa! WHAT?!?! Danger zone!!!!!! Anyway, this is pretty minor stuff. But, I happen to come across the need for these data-type of conversions on a fairly regular basis.




Reader Comments

Quick pedantic note: as of CF7 Adobe recommends against using toString, toBinary and toBase64; and instead using CharsetEncode, BinaryDecode, and BinaryEncode, respectively. You've got a mixture going on in the code above.

As an aside, what versions of CF to your want Crypto.cfc to work with? I believe it's currently limited to >= 8, due to script only cfc.

@Grumpy,

Definitely I use toBase64() rather than binaryEncode() out of habit. I would be fine switching over to binaryEncode() for that. However, I am not sure how comfortable I am with the charsetEncode() method. I don't believe I have ever used it; and, the documentation for it looks a bit confusing. I'll have to look into it a bit more to see how it works.

As far as Crypto.cfc, I didn't think much about the compatibility. I built it in CF9, but it should work with CF8 as well. I don't even have any instances of CF7 to test on ; but, CF8 introduced so many syntactic updates that writing things for CF7 compatibility would probably not be worth-while.

@Ben

w00t! Thankfully the new functions are tucked away in helper functions which are even easier to read then the old CF functions. :-)

@Grumpy,

I think I can be sold on using it :) The one thing that keeps tripping me up is the seeming conflict (in my brain) between the meaning of "encode".

With binaryEncode(), I read it as, "encode this binary value as something else."

This causes me to ready charsetEncode() as "encode this character set as something else."

... but, charsetEncode() actually means just the opposite - "encode something else [binary value] as a character set".

Of course, this probably stems from me completely misunderstanding the meaning of "charset" as it probably has more to do with the range of values rather than my mental model of "string" characters.

Hey Ben - great examples, but when you say 'I left out the following data type conversions because they can already be performed in ColdFusion using a single line of code:' , you really didn't leave them out did you for stringToBase64() - as its simply the toBase64( stringValue ), but instead you're doing the conversion to Binary and then from Binary to base 64 - few extra steps that the one liner does.

So I guess I'm just confused - did you mean to leave those functions in place, or replace them with the one liner equivalent in cf already?