Search Smith

ColdFusion, SQL queries, and, of course, searching

Posts Tagged ‘ColdFusion’

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.

Posted in ColdFusion | Tagged: , , , , , | 2 Comments »

ColdFusion 9: Preserving sort order with structs

Posted by David Faber on January 28, 2012

In a previous post I talked about using structs to avoid using CFQUERY inside a query loop. Structs are also useful if you need to return your data in JSON format (of course, ColdFusion can return query objects in JSON format as well, but I think this format can be difficult to use if you’re using something other than ColdFusion to read it back in). In this vein, it would be helpful if structs retained sort order. This helpful blog post shows how to do just that.

Posted in ColdFusion | Tagged: , , , | Leave a Comment »

ColdFusion 9 and Solr: MultiValued fields vs. Tokenized

Posted by David Faber on January 17, 2012

I was indexing a new collection yesterday and kept getting out of memory errors from the JVM (in truth, I don’t know if they were from JRun or from whatever JVM Solr was running in). Apparently either CF didn’t like the huge array I was generating, or Solr didn’t like me trying to cram it into a multiValued field of type slong. I decided to try something different – I created a space-delimited list of terms instead (they were all numbers, so no need to worry about phrases or anything like that). That worked great.

According to this question/answer thread on StackOverflow, there should not be a difference in results if that field is used for filtering. There may be a difference in scoring, but as I was only using the field for filtering anyway, that is not a concern.

Posted in ColdFusion, Solr | Tagged: , , , | Leave a Comment »