在.NET中,如何解密使用Java中的PBEWithMD5AndDES加密的值?

时间:2013-12-13 16:47:34

标签: c# .net hibernate encryption jasypt

我们正在将遗留Java应用程序中的数据迁移到我们较新的.NET应用程序中。 Java应用程序有一个MySQL后端,而.NET应用程序有一个SQL Server后端。我们有完整的源代码和配置文件,但是没有一个开发Java应用程序的开发人员仍在公司,我们不得不对一些逻辑进行逆向工程以迁移数据。在我们的测试中,我们已经将大部分数据正确地移动了。但是有一列加密值我们遇到了麻烦。

据我所知,Java应用程序中没有显式调用方法来在访问时加密或解密列。相反,加密似乎是在用于访问数据的ORM内自动发生的(Hibernate)。我找到了一个名为/entities/TABLENAME.hbm.xml的XML文件,我认为该文件是Hibernate对该列的模型定义。 XML文件中的相关行如下:

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

请注意,类型为stringEncryptedstringEncrypted的定义似乎位于/entities/global/User.hbm.xml中,如下所示:

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

然后stringEncrypter设置似乎在/webapp/resources/spring/CompanyName-encryption.xml中,如下所示(当然已经过消毒):

<!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>

所以,我认为这告诉我,该列是使用PBEWithMD5AndDES方法加密加密的,使用密码PASSWORDSALTSALTSALTSALTSALTSALTSALTSALTSALT的盐。那么,问题是如何解密.NET中的列值

到目前为止,我最好的领导是Tom Hundley发布的PKCSKeyGenerator class。使用它,我在.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);

当我跑步时,我得到:

CryptographicException: Bad Data

我一直在寻找其他解密方法,扫描Java代码以查找可能正在使用的任何其他代码,并修改了PKCSKeyGenerator中的参数,但我没有取得任何进展。我似乎无法使这个解密工作。你有什么建议吗?提前谢谢。

2 个答案:

答案 0 :(得分:1)

问题中提到的Tom Hundley的PKCSGenerator类似乎正确地实现了非标准的“PBEwithMD5andDES”密钥派生算法。您缺少的部分是迭代次数,您在问题中显示为13。 (对于DES,segment参数应为1;对于DES,对于三重DES,这将增加,具体取决于所使用的键控选项。)

在我检查的版本中,Jasypt密钥派生算法的默认迭代次数仅为1000(StandardPBEByteEncryptor.DEFAULT_KEY_OBTENTION_ITERATIONS的值)。

由于您要删除加密,因此这足以让您继续使用.NET。如果您想保留加密,我强烈建议您迁移加密列,以便它们使用PKCS#5中的PBKDF2和AES进行加密。如果你这样做,我会使用更多的迭代,可能是50,000到100,000,具体取决于你可用的资源。

答案 1 :(得分:0)

我会读到这个:

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

您将遇到的问题是猜测MD5被哈希的次数。