Question

We're migrating data from a legacy Java app into our newer .NET app. The Java app has a MySQL backend, and the .NET app has a SQL Server back end. We have the full source code and config files for both, but none of the developers who worked on the Java app are still with the company, and we're having to reverse-engineer some of the logic in order to migrate the data. We have most of the data moving over properly in our tests. But there's one column with encrypted values that we're having trouble with.

As far as I can tell, no methods are explicitly being called in the Java app to encrypt or decrypt the column when it's accessed. Rather, the encryption seems to be be happening automatically inside the ORM being used to access the data (Hibernate). I found an XML file named /entities/TABLENAME.hbm.xml that I believe to be Hibernate's model definition for the column. The relevant lines inside the XML file are as follows:

<property name="columnname" type="stringEncrypted">
    <column name="TBL_COLUMNNAME" not-null="false" unique="false" sql-type="VARCHAR(255)"/>
</property>

Note that the type is stringEncrypted. The definition for stringEncrypted appears to be in /entities/global/User.hbm.xml, as follows:

<typedef name="stringEncrypted" class="org.jasypt.hibernate.type.EncryptedStringType">
    <param name="encryptorRegisteredName">stringEncrypter</param>
</typedef>

And then the stringEncrypter settings appear to be in /webapp/resources/spring/CompanyName-encryption.xml as follows (sanitized, of course):

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
        <bean id="stringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
            <property name="password">
                <value>PASSWORD</value>
            </property>
            <property name="algorithm">
                <value>PBEWithMD5AndDES</value>
            </property>
            <property name="saltGenerator">
                <ref bean="fixedStringSaltGenerator"/>
            </property>
        </bean>

        <bean id="fixedStringSaltGenerator" class="org.jasypt.salt.FixedStringSaltGenerator">
            <property name="salt">
                <value>SALTSALTSALTSALTSALTSALTSALTSALTSALT</value>
            </property>
        </bean>

        <bean id="hibernateEncryptor" class="org.jasypt.hibernate.encryptor.HibernatePBEStringEncryptor">
            <property name="registeredName">
                <value>stringEncrypter</value>
            </property>
            <property name="encryptor">
                <ref bean="stringEncryptor" />
            </property>
        </bean>
    </beans>

So, what I think this tells me, is that the column is being encrypted with PBEWithMD5AndDES-method encryption, using a password of PASSWORD and a salt of SALTSALTSALTSALTSALTSALTSALTSALTSALT. So, the question is how can I decrypt the column values in .NET?

My best lead so far is this PKCSKeyGenerator class posted by Tom Hundley. Using that, I've attempted the following in .NET:

string encryptedInput = "mG5bz6duwBL3jVCLKyI8Zw=="; // This is an encrypted value copied from MySQL Workbench
string saltString = "SALTSALTSALTSALTSALTSALTSALTSALTSALT";
string keyString = "PASSWORD";
byte[] saltBytes = new byte[saltString.Length * sizeof(char)];

System.Buffer.BlockCopy(saltString.ToCharArray(), 0, saltBytes, 0, saltBytes.Length);

PKCSKeyGenerator crypto = new PKCSKeyGenerator(
    keyString, // key
    saltBytes, // salt
    13, 1); // Magic numbers. I don't really get 'em.
ICryptoTransform ct = crypto.Decryptor;

byte[] cipherBytes = Convert.FromBase64String(encryptedInput);
byte[] clearBytes = ct.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length);
string clearString = Encoding.Unicode.GetString(clearBytes);

When I run this, I get:

CryptographicException: Bad Data

I've looked around for other decryption methods, scanned the Java code for any other code that might be in use, and tinkered with the parameters in of PKCSKeyGenerator, and I've made no progress. I just can't seem to make this decription work. Do you have any suggestions? Thanks in advance.

Was it helpful?

Solution

Tom Hundley's PKCSGenerator class mentioned in the question appears to correctly implement the non-standard "PBEwithMD5andDES" key derivation algorithm. The piece you are missing is the number of iterations, which you show as 13 in the question. (The segments parameter should be 1, as you show, for DES; for triple-DES, this would increase, depending on the keying option used.)

In the version I checked, the default number of iterations for Jasypt's key derivation algorithm is only 1000 (the value of StandardPBEByteEncryptor.DEFAULT_KEY_OBTENTION_ITERATIONS).

Since you are removing encryption, this should suffice to allow you to proceed with .NET. If you wanted to keep the encryption, I would strongly recommend migrating the encrypted columns so that they are encrypting using PBKDF2 from PKCS #5 together with AES. If you were to do that, I'd use far more iterations, maybe 50,000 to 100,000 depending on the resources you have available.

OTHER TIPS

I would read this:

http://www.codeproject.com/Articles/16450/Emulating-PBEWithMD5AndDES-Encryption-under-NET

The problem that you're going to have is the guessing at the number of times the MD5 was hashed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top