ColdFusion Encryption from .NET Membership Tables

289 Views Asked by At

I have a client who is implementing ZNode which uses the aspnet_Membership table to store a password. This table contains an encrypted password, the password salt and is using the "PasswordFormat" of 2. From what I gather, "2" is a recoverable encrypted password.

The ColdFusion server is BlueDragon 9 Alpha. If you don't know BD, no worries, anything that ColdFusion supports "should" work and I have CF 10 to test it on as well.

If you know a better way to do this I'm all ears. I need to be able to create a user/password and store it in the ASP membership table via ColdFusion. In addition I need to be able to check the user/password for login.

When looking at the Web.config file, the ZnodeMembershipProvider is a "System.Web.Security.SqlMembershipProvider" type.

The machineKey entry looks like this: (took out the two key values)

<machineKey decryption="AES" 
     decryptionKey="[64 character string]" 
     validation="SHA1" 
     validationKey="[128 character string]"/>

If I try something like this:

Encrypt('myPassword', '[64 character string]', 'AES', 'Base64')

It says "Specified key is not a valid size for this algorithm."

I'm not very savy on encryption or .NET. Thanks in advance.

2

There are 2 best solutions below

1
On

This answer I wrote up, about DNN (Dot Net Nuke) authentication, should do the trick. (Assuming no differences between ACF and BD). Essentially there are few difference in how .NET and CF handle encryption. The primary differences are:

  1. Encoding:
    • .NET uses UTF-16LE
    • CF always uses UTF-8. In ACF, this means you must use encryptBinary instead of encrypt. (I am not sure about OBD).

  2. Key Format:

    • .NET uses hexadecimal
    • CF typically uses base64, so you may need to convert the keys first.

  3. Encryption Mode:

    • .NET defaults to CBC mode (requires IV)
    • CF defaults to ECB (no IV required)

In case the other link dies, here is the full example. While it uses 3DES, the basic concept is the same for AES. Note: In Java, the larger key sizes (ie 192,256) are only available if the Sun Unlimited Strength Jurisdiction Policy Files are installed.

3DES Example:

// sample valus
plainPassword = "password12345";
base64Salt    = "x7le6CBSEvsFeqklvLbMUw==";
hexDecryptKey = "303132333435363738393031323334353637383930313233";

// first extract the bytes of the salt and password
saltBytes = binaryDecode(base64Salt, "base64");
passBytes = charsetDecode(plainPassword, "UTF-16LE" );

// next combine the bytes. note, the returned arrays are immutable, 
// so we cannot use the standard CF tricks to merge them   
// NOTE: If BlueDragon does not include "org.apache.commons...."
// just loop through the arrays and merge them manually
ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils");
dataBytes = ArrayUtils.addAll( saltBytes, passBytes );

// convert DNN hex key to base64 for ColdFusion
base64Key  = binaryEncode(binaryDecode( hexDecryptKey, "hex"),  "base64");

// create an IV and intialize it with all zeroes
// block size:  16 => AES, 8=> DES or TripleDES 
blockSize = 8; 
iv = javacast("byte[]", listToArray(repeatString("0,", blocksize)));

// encrypt using CBC mode 
bytes = encryptBinary(dataBytes, base64Key, "DESede/CBC/PKCS5Padding", iv);

// result: WBAnoV+7cLVI95LwVQhtysHb5/pjqVG35nP5Zdu7T/Cn94Sd8v1Vk9zpjQSFGSkv 
WriteOutput("encrypted password="& binaryEncode( bytes, "base64" ));
0
On

I believe that .NET Password tables use Triple-DES, not AES. Try this instead.

Encrypt('myPassword', '[64 character string]', '3DES', 'Base64')