Converting A Base64 Value Back Into A String Using ColdFusion

Posted September 5, 2008 at 2:54 PM by Ben Nadel

Tags: ColdFusion

This might seem super obvious to some of you, but this small problem had me stumped for a good 10 minutes this morning. I had an XML value that I was converting to Base64 for an HTTP post. Then, on the other side, I needed to take that Base64 encoded value and convert it back to a regular string for use with XML parsing. And then it hit, I had no idea how to, in ColdFusion, take a Base64 encoded value and convert it back to the original string.

Once I figured it out, it was laughably simple:

  • <!--- Create a string value. --->
  • <cfset strValue = "Hey there cutie patootie." />
  •  
  • <!--- Convert to base 64. --->
  • <cfset strBase64Value = ToBase64( strValue ) />
  •  
  • <!---
  • To convert the base 64 value back to string, simply convert
  • the it a binary representation and then back into to a string.
  • --->
  • <cfset strNewValue = ToString( ToBinary( strBase64Value ) ) />
  •  
  • <!--- Output test data. --->
  • <p>
  • <cfoutput>
  • Base 64: #strBase64Value#<br />
  • Value: #strNewValue#
  • </cfoutput>
  • </p>

Running the above code, we get the following output:

Base 64: SGV5IHRoZXJlIGN1dGllIHBhdG9vdGllLg==
Value: Hey there cutie patootie.

In ColdFusion, the ToBinary() function takes a Base64 encoded value and converts it to its binary representation. This, of course, is a Byte Array. In our example, where each character of a string is represented by a single byte, we have one character per byte array index. Then, calling ToString() on that Byte Array simply converts that character-based byte array back into its string representation.




Reader Comments

Sep 5, 2008 at 3:11 PM // reply »
12 Comments

I've done something similar in a MS SQL Server database - take a text field and output as string:

CAST(CAST(textField AS VARBINARY(1000)) AS VARCHAR(1000))

I think that's how it worked. I'm fairly sure most DBMSs have similar functions.


Sep 5, 2008 at 3:42 PM // reply »
9 Comments

Earlier this week, I had to do the same thing except that the strValue was a GUID (hex). I found that converting the GUID to decimal and then trying to run ToBase64 on the resulting HUGE number resulted in a CF error. Apparently ToBase64 can only handle decimals up to a certain size. I did find the solution though (with Ray's help) and posted it here: http://www.coldfusionjedi.com/forums/messages.cfm?threadid=2E1AFB13-19B9-E658-9DEC415EB6931B97

Enjoy!


Sep 5, 2008 at 4:04 PM // reply »
6 Comments

Just FYI Ben. The CFML Reference manual is your friend. It's on page 1228.


Sep 5, 2008 at 4:24 PM // reply »
11,243 Comments

@Matt,

Good to know.

@John,

I assume you needed to go to a decimal first for some reason; otherwise, you can convert any string to Base64 regardless of length.

@Gary,

It's funny, I have gone from String -> Base64 -> Binary so many times that I totally blanked on going the reverse order.

ps. I love the CFML Reference guide :)


Sep 5, 2008 at 4:52 PM // reply »
9 Comments

@Ben,

Yes. Per my post on coldfusionjedi.com, I needed a *shorter* version of the GUID. If you treat it as a (hex) number, the resulting Base64 has fewer characters/digits than the original:

GUID: e1c4c2926-b394-6808-e611-f95a4c41cbf
Base64: 4cTCkms5RoCOYR+VpMQcvw==

If you treat the GUID as a string, the resulting Base64 has more characters/digits than the original:

GUID: e1c4c2926-b394-6808-e611-f95a4c41cbf
Base64: ZTFjNGMyOTI2YjM5NDY4MDhlNjExZjk1YTRjNDFjYmY=

Make sense?

I discovered this phenomenon on Wikipedia, of all places, "When printing fewer characters is desired, GUIDs are sometimes encoded into a base64 or Ascii85 string. Base64-encoded GUID consists of 22 to 24 characters (depending on padding)."

http://en.wikipedia.org/wiki/GUID


Sep 5, 2008 at 4:56 PM // reply »
11,243 Comments

@John,

Ahh, yes, that makes sense. Thanks for the clarification.


Apr 26, 2011 at 5:53 PM // reply »
4 Comments

@John, thanks the hex tip. One thing I've found is the GUIDs are coming back with some 0's missing. Did you notice this?

GUID before: 3D0F1C1C-E3F6-11D3-896A-00105A7027AA

"GUID" after: 3DF1C1CE-3F61-1D38-96A0-105A7027AA


Apr 26, 2011 at 6:09 PM // reply »
9 Comments

@Jason No, I either didn't notice that or didn't have that problem and, since Sep 2008, my need for this bit of logic went away and the code in question is not easily accessible. Perhaps you can share your code?


Apr 26, 2011 at 6:11 PM // reply »
4 Comments

@John, It's your original code, I copy/pasted and used it for testing. No biggie, just wondering if it did the same for you. Thx


Apr 26, 2011 at 6:15 PM // reply »
9 Comments

@Jason My bad. Right there it is at http://www.coldfusionjedi.com/forums/messages.cfm?threadid=2E1AFB13-19B9-E658-9DEC415EB6931B97 No, I didn't notice what you're describing. I was using ACF8. You?


Apr 26, 2011 at 6:30 PM // reply »
4 Comments

@John, should be the same as yours unless my CF default is somehow different.


Apr 26, 2011 at 6:40 PM // reply »
9 Comments

@Jason Try these and let me know. I think I might have fixed it and forgotten to update post on Ray's site. If this works, let me know and I will...

<cffunction access="public" name="HexToBase64" output="yes" returntype="string">
<cfargument name="Hex" type="string" required="yes">
<cfset Hex = Replace(Hex, "-", "", "ALL")>
<cfset outStream = CreateObject("java", "java.io.ByteArrayOutputStream").init()>
<cfset inputLength = Len(Hex)>
<cfset outputString = "">
<cfset i = 0>
<cfset ch = "">
<cfif inputLength mod 2 neq 0>
<cfset Hex = "0" & Hex>
</cfif>
<cfloop from="1" to="#inputLength#" index="i" step="2">
<cfset ch = Mid(Hex, i, 2)>
<cfset outStream.write(javacast("int", InputBaseN(ch, 16)))>
</cfloop>
<cfset outStream.flush()>
<cfset outStream.close()>
<cfreturn ToBase64(outStream.toByteArray())>
</cffunction>

<cffunction access="public" name="Base64ToHex" output="yes" returntype="string">
<cfargument name="Base64" type="string" required="yes">
<cfset aBinary = ToBinary(Base64)>
<cfset Hex = "">
<cfloop index="i" from="1" to="#ArrayLen(aBinary)#">
<cfset Hex = Hex & Replace(RJustify(FormatBaseN(BitAnd(aBinary[i], 255), 16), 2), " ", "0", "ALL")>
</cfloop>
<cfset Hex = Insert("-", Hex, 20)>
<cfset Hex = Insert("-", Hex, 16)>
<cfset Hex = Insert("-", Hex, 12)>
<cfset Hex = Insert("-", Hex, 8)>
<cfreturn Hex>
</cffunction>


Apr 27, 2011 at 11:54 AM // reply »
4 Comments

@John, that worked, thanks for the update!


Apr 27, 2011 at 11:56 AM // reply »
9 Comments

@Jason You're welcome!



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 22, 2013 at 5:35 PM
Script Tags, jQuery, And Html(), Text() And Contents()
This is still an issue 2 years later. jQuery is supposed to remediate these cross browser issues, no? I have been unable to find any statement from the jQuery team calling this behavior "by de ... read »
May 22, 2013 at 12:44 PM
Ask Ben: Query Loop Inside CFScript Tags
In cf10, if you call a function that has: local.result = {}; local.result.msg = ""; local.svc = new query(); local.svc.setSQL("SELECT * FROM..."); local.obj = local.svc.exe ... read »
May 22, 2013 at 12:29 PM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben: What version of Java are you using? Also, did you test users.id to see what Java reports as the data type? I wonder if it's not a Java primitive data type, but getting returned as something ... read »
May 22, 2013 at 11:47 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dana, Awesome - so it looks like this bug was fixed in ColdFusion 10. Thanks so much for double-checking that. ... read »
May 22, 2013 at 11:37 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
When I c&p and run on cf10, I get: Selected User IDs: 1,4 User 1 selected: YES - YES User 2 selected: NO - NO User 3 selected: NO - NO User 4 selected: YES - YES User 5 selected: NO - ... read »
May 22, 2013 at 11:27 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Tom, Good thought, but no dice. Both of these still exhibit the same behavior: users.id[ users.currentRow ] users[ "id" ][ users.currentRow ] It's just something whacky happening with ... read »
May 22, 2013 at 11:07 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
Could your problem be that "users.id" is actually an ARRAY, not a single value? Perhaps try it again with "users.id[1]" (I only have CF8 here at work). ... read »
May 22, 2013 at 7:52 AM
Nested Views, Routing, And Deep Linking With AngularJS
Hi, Just a quick thank you. As it happens, for my own purposes, the pending ui-router work being done in native angular is likely the one I'll adopt, but your exploration, code and documentation of ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools