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

标签 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 加密方法加密,使用密码 PASSWORD 和盐 SALTSALTSALTSALTSALTSALTSALTSALT。所以,问题是如何解密 .NET 中的列值

到目前为止,我最好的线索是 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 中的参数,但我没有取得任何进展。我似乎无法使这种描述有效。你有什么建议吗?提前致谢。

最佳答案

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

在我查看的版本中,Jasypt 的 key 推导算法的默认迭代次数仅为 1000(StandardPBEByteEncryptor.DEFAULT_KEY_OBTENTION_ITERATIONS 的值)。

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

关于c# - 在 .NET 中,如何解密在 Java 中使用 PBEWithMD5AndDES 加密的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20571685/

相关文章:

c# - facebook sdk邀请 friend 申请

c# - 根据优先级数组对字符串数组进行排序

java - 是否可以暂时禁用 Hibernate 实体的级联?

java - 仅记录当前线程/ session 的 Hibernate SQL 的最简单方法

c# - 使用 Web API v2 的全局集合

.net - 使用 ViewModel 中定义的 RelayCommand 传递参数(来自 Josh Smith 示例)

c# - 如何在通过管道进行Azure DevOps部署期间删除本地wwwroot文件夹的内容?

c# - 使用 GUID 是生成随机字符串和数字的有效方法吗?

java - Hibernate 从控制台记录异常

c# - 如何在 WPF 后端正确使用 .NET 数据注释进行数据验证?