Search Smith

ColdFusion, SQL queries, and, of course, searching

ColdFusion 9: Getting TripleDES to play nice with .Net

Posted by David Faber on February 6, 2012

I recently had the opportunity to try to implement TripleDES encryption in ColdFusion to try and talk to another piece of software written in .Net. Should be simple and straightforward, right? Actually, it turned out to be rather painful – in part because the fix was so easy.

The reference page for ColdFusion’s encrypt() function on Adobe’s web site states that the algorithm “DES-EDE” is used for Triple DES encryption. This is a typo; the correct algorithm is “DESEDE” (without the hyphen). On the other hand, an article in Adobe’s knowledgebase on strong encyrption with ColdFusion states that “TripleDES” can be used as a synonym for “DESEDE”. This is true, but only to a point, as we will see below.

First, here is some ColdFusion code that uses .Net’s implementation of Triple DES in order to encrypt a string:

<cfset utf8_encoder = createObject("dotnet", "System.Text.UTF8Encoding") />
<cfset ascii_encoder = createObject("dotnet", "System.Text.ASCIIEncoding") />

<cfset cipher_mode = "ECB" />
<cfset padding_mode = "PKCS7" />

<cfquery name="get_key" datasource="#application.datasource#">
    SELECT 'ABCDEFGHIJKLMNOPRSTUVWYZ' AS key_value, '@vector@' AS init_vector
      FROM dual
</cfquery>

<cfset key_array = utf8_encoder.GetBytes(get_key.key_value) />
<cfset iv_array = ascii_encoder.GetBytes(get_key.init_vector) />

<cfset to_encrypt = "a@b.com" />
<cfset to_encrypt_array = utf8_encoder.GetBytes(to_encrypt) />

<cfset tdes = createObject("dotnet", "System.Security.Cryptography.TripleDESCryptoServiceProvider") />
<cfset tdes.Set_Key(key_array) />
<cfset tdes.Set_IV(iv_array) />
<cfset tdes.Set_Mode(createObject("dotnet", "System.Security.Cryptography.CipherMode")[cipher_mode]) />
<cfset tdes.Set_Padding(createObject("dotnet", "System.Security.Cryptography.PaddingMode")[padding_mode]) />

<cfset the_encryptor = tdes.CreateEncryptor() />

<cfset resultArray = the_encryptor.TransformFinalBlock( to_encrypt_array, 0, arrayLen(to_encrypt_array) ) />
<cfset the_encrypted_string = createObject("dotnet", "System.Convert").ToBase64String( resultArray ) />

Yes, you really do have to do all that work just to encrypt a simple string using .Net’s implementation of Triple DES. In fact, it is not much more work to do this in ColdFusion than it is to do it in .Net. This seems like a far cry from how ColdFusion does things:

<cfset the_encrypted_string = encrypt(to_encrypt, get_key.key_value, "DESEDE/#cipher_mode#/#padding_mode#Padding", "Base64", get_key.init_vector) />

One line of code vs. about 15 lines of code – not too bad! The problem is that the results won’t be the same:

CF: bhPAwaCFmCo=
.Net: 6FJVEJ8bMac=

To make a long story short, after some poking around I found out (thanks to a very helpful post on StackOverflow) that the key must be base64-encoded in the call to encrypt():

<cfset the_encrypted_string = encrypt(to_encrypt, toBase64(get_key.key_value), "DESEDE/#cipher_mode#/#padding_mode#Padding", "Base64", get_key.init_vector) />

And then the results will be the same:

CF: 6FJVEJ8bMac=
.Net: 6FJVEJ8bMac=

Now here’s where things get a little bit curious. As I mentioned above, Adobe claims that “TripleDES” is a synonym for “DESEDE” when used in the encrypt() function. But when we try to plug it in here:

<cfset the_encrypted_string = encrypt(to_encrypt, toBase64(get_key.key_value), "TripleDES/#cipher_mode#/#padding_mode#Padding", "Base64", get_key.init_vector) />

ColdFusion throws an error:

The TripleDES/ECB/PKCS7Padding algorithm is not supported by the Security Provider you have chosen.

Now, this can be gotten around by using PKCS5Padding instead of PKCS7, and the two seem to be compatible. However, I don’t think I would want to try to explain that to a client in the event that something goes wrong. More curious is this:

<cfset the_encrypted_string = encrypt(to_encrypt, get_key.key_value, "TripleDES/#cipher_mode#/PKCS5Padding", "Base64", get_key.init_vector) />

“TripleDES” throws an error (The key specified is not a valid key for this encryption: Wrong key size.), while “DESEDE” happily encrypts the string anyway, but gives the wrong result! Just a head’s up for those who need to get ColdFusion and .Net talking to one another.

2 Responses to “ColdFusion 9: Getting TripleDES to play nice with .Net”

  1. Mike said

    Thanks,

    I beat my head against the wall trying to match a .NET with just CF. I could not do it, so I borrowed your .NET example and commented out the cipher and padding and it matches. I tried setting ECB and NoPadding but that did not do it. I must have to do something else on the keys.

    Thanks again for posting.

  2. David Faber said

    Mike: Glad I could be of help, even if it is two years after I first wrote this post!

Leave a Comment

Your email address will not be published. Required fields are marked *