Joshua Carmody Joshua Carmody - 2 months ago 14
C# Question

In .NET, how can I decrypt values that were encrypted using PBEWithMD5AndDES in Java?

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.

Answer

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.