【问题标题】:In .NET, how can I decrypt values that were encrypted using PBEWithMD5AndDES in Java?在 .NET 中,如何解密在 Java 中使用 PBEWithMD5AndDES 加密的值?
【发布时间】:2016-09-14 12:40:05
【问题描述】:

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

据我所知,Java 应用程序中没有显式调用任何方法来在访问列时对其进行加密或解密。相反,加密似乎是在用于访问数据的 ORM 内自动发生的(休眠)。我找到了一个名为/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 和盐SALTSALTSALTSALTSALTSALTSALTSALTSALT。那么,问题是如何解密 .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 中的参数,但我没有取得任何进展。我似乎无法使这个描述起作用。你有什么建议吗?提前致谢。

【问题讨论】:

  • DES 不安全,Java PBEWithMD5andDES 算法不遵循 PKCS #5 标准。与其尝试在 .NET 中重新创建当前的加密过程,不如选择修改数据库?然后,您可以使用 Java 代码解密当前字段,并使用更易于在 .NET 中支持的体面算法重新加密它们。
  • @erickson - 目标是让数据在未来永久保持未加密状态。我们对实现这一目标的任何方法感到满意。我们尝试只用 Java 解密数据,但我们很难让旧的 Java 代码编译和运行,因为我们现在使用的技术堆栈与编写应用程序时完全不同。我们可以继续尝试,但我希望在 .NET 中解密数据比尝试恢复 Java 代码更容易。
  • @erickson - 同意,DES 不安全。当有更强大的选项可用时,为什么 Jasypt 默认使用 PBEWithMD5andDES?

标签: c# .net hibernate encryption jasypt


【解决方案1】:

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

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

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

【讨论】:

  • 我可以从哪里开始学习这些不同的算法、加密和解密。我知道一些零碎的东西,但可以从软件开发中的安全实践的基本知识开始
【解决方案2】:

我会读这个:

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

您将遇到的问题是猜测 MD5 被散列的次数。

【讨论】:

  • 你知道有什么方法可以从 Java 代码中找出 MD5 被散列了多少次吗?有默认值吗?还是我应该寻找的地方?
  • 另外,那篇文章中的 PKCSKeyGenerator 类是我链接到的类的基础。我看过他们两个,但我很难完全理解他们的代码中发生了什么。
  • 我尝试在 for 循环中运行解密,尝试从 0 到 100 的每个 MD5 哈希迭代次数。其中一些不会抛出异常,但那些不会t 产生垃圾输出。我的方法一定有其他问题。目前正在尝试查看两个系统之间的文本编码是否不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多