Link to home
Start Free TrialLog in
Avatar of cshark247
cshark247

asked on

How to Decrypt in C# a string that is encrypted with Coldfusion Encrypt(string, seed) function

I have encrypted strings in SQL server that was encrypted using Coldfusion MX Encrypt

 Encrypt("test string", "my Key"

 I have read value in data set using C# code and i want to decrypt this value.

 Thanks in Advance for any help.
Avatar of Ryan Chong
Ryan Chong
Flag of Singapore image

if you're talking about data recovery to its original content, probably the better way is to create back a temporary CF web server and decrypt the string in CF itself, and store this original value to other column in your SQL Server database.

The converted string (using CF command: decrypt) and its success rates also depending on the complexity of key and algorithm previously used to encrypt the data.
Avatar of cshark247
cshark247

ASKER

Hi Ryan,

I am developing a module that has to access data saved by coldfusion to MS SQL, in my .net  c# code I need to read that encrypted data, decry-pt it and consume it. data is encrypted using a string as Seed as I mentioned in my question. Key used is 3 letter string that I know.

Thanks
EDIT: The CFMX_COMPAT algorithm isn't compatible with any built in algorithm in C#, and is also very insecure.  Might be a custom C# implementation floating around. However, IMO your best bet is to switch to a stronger algorithm that's compatible with both sides, like AES. As Ryan suggested, you can easily set up a CF script to pull out the data and decrypt it.  Then re-encrypt it with a new algorithm and store the new values back in the db.

If you absolutely can't change the CF code for some reason, another option is to set up a CF web service that does the decryption. Then call it from C# over ssl.  Though again, for better security, I'd recommend switching to a more robust and compatible algorithm.
cshark247 - Any updates? Is it possible to decrypt/re-encrypt with a different algorithm on the CF side OR have CF do the decryption? Not sure how much flexibility you have in your environ.
Since my module has to co-exist with other modules written in ColdFusion, the best solution would be a C# code that can decrypt data encrypted by ColdFusion. so that both ColdFusion modules and my new .net modules can work on same data.

Thanks!
Well, you have 3 choices:

1) Change the CF code - and have encrypt() use strong encryption like AES. Then the result will be compatible with C# out of the box. See example below.
Pros:  Secure and Compatible with both CF and C#
Cons: Requires decrypting/re-encrypting existing values in CF

2)  Find a custom C# implementation - Try and find a custom C# library that's implemented the old algorithm CF is using. Cons: Might be hard to find, Algorithm is insecure.
Pros:  Requires no changes to the CF code
Cons: May be hard to find a custom lib for this obscure algorithm.  Insecure.

3) Hybrid Approach - Do the work on the CF side.  Set up a CF webservice to decrypt the values and call it from CF
Pros:  Requires no changes to the existing CF modules
Cons:  Requires a web service call from C#


Here's an example just to show how easy it is to change the CF encrypt() code to use AES - only 2 extra params. Notice the result can also be decrypted in C# with existing libraries?

Encrypt in CF:
<cfscript>
    key = "zPjG2QiCmkKqR3RNQoNkzg==";
    text = "The quick brown fox jumps over the lazy dog";
    
    encrypted = encrypt(text, key, "AES/ECB/PKCS5Padding", "base64");
    
    writeDump(encrypted);
</cfscript>

Open in new window


Decrypt in C#
:
using System.IO;
using System;
using System.Security.Cryptography;

class Program
{
    static void Main()
    {
        
        byte[] key = Convert.FromBase64String("zPjG2QiCmkKqR3RNQoNkzg==");
        byte[] data = Convert.FromBase64String("uzClkJnMBG+fJpI0CXkAa52p1G8KmEnQgoKfX0GeXuw9WgjZDmtmxu9oW7gUPuD5");


        using (RijndaelManaged algorithm = new RijndaelManaged())
        {

            // initialize settings to match those used by CF
            algorithm.Mode = CipherMode.ECB;
            algorithm.Padding = PaddingMode.PKCS7;
            algorithm.BlockSize = 128;
            algorithm.KeySize = 128;
            algorithm.Key = key;
        
            ICryptoTransform decryptor = algorithm.CreateDecryptor();
        
            using (MemoryStream ms = new MemoryStream(data))
            {
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                   using (StreamReader sr = new StreamReader(cs))
                   {
        
                        Console.WriteLine("Decrypted: {0}", sr.ReadToEnd());
                   }
                }
            }
        }

    }
}

Open in new window

Option #1 would be the best, and is simpler than it sounds, but I don't know if you have the flexibility to change the existing CF code.

If not, you're stuck with #2 or #3.  Option #2 would be the cleanest, but not sure if there even are any custom libs out there that do this. So that leaves #3.  The CF dev's could set up a script or webservice that does the decrypt. Then all you need to do from C# is an http call.
Thanks a lot for a very good solution, I agree that option 1 is best approach.  What changes in ColdFusion code that decrypts would be needed if we update all values using new encryption  encrypt(text, key, "AES/ECB/PKCS5Padding", "base64"); ?
ASKER CERTIFIED SOLUTION
Avatar of _agx_
_agx_
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks a lot for helping on this one!
Anytime. Glad to help.

Edit: Btw, though CF defaults to AES/ECB, consider using AES/CBC. It's not that much harder to implement.