【问题标题】:decrypt PBEWithMD5AndTripleDES encrypted string in .net在 .net 中解密 PBEWithMD5AndTripleDES 加密字符串
【发布时间】:2021-03-26 05:49:18
【问题描述】:

我需要使用使用 PBEWithMD5AndTripleDES 算法的 org.jasypt.util.text.StrongTextEncryptor 解密在 Java 中生成的字符串。我想我在这里找到了源代码:http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndTripleDESCipher.java

它有一些关于算法的信息:

  1. 创建随机盐并将其分成两半。如果两半相同,则反转其中之一。
  2. 将密码与每一半连接起来。
  3. 使用 c 次迭代来消化每个串联,其中 c 是迭代计数。将每个摘要轮的输出与 密码,并将结果用作下一个摘要的输入 手术。摘要算法为 MD5。
  4. 经过 c 次迭代,使用 2 个结果摘要,如下所示:第一个摘要的 16 个字节和第二个摘要的第一个 8 个字节
    形成三重 DES 密钥,以及第二个摘要形式的最后 8 个字节 IV.

Java 中的代码看起来非常简单。这就是密钥的解密方式。

    StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
    textEncryptor.setPassword(key1);
    String result = textEncryptor.decrypt(key2);

这是我生成的一个示例:

key1=17EXGCnC
key2=7bALjokBDuxopB+Z37DwiTX/jg3/pjUoKW4q25uzd34=
result=-1,-1

谁能指导我如何实现解密代码?

这是Java中使用的包:https://mvnrepository.com/artifact/com.melloware/jasypt/1.9.4

【问题讨论】:

  • 代码令人困惑,因为您确实拥有密钥和加密数据。 Key2 是加密数据。要解密,您应该有一个密钥和加密的消息。您的解密方法只有一个参数。
  • 是的,我知道,但我不知道该怎么做。也许我应该写 c# 代码来表明我已经开始研究它,但正如你所说的还没有走远。
  • 见下文。你需要三样东西 1) 公钥 2) 私钥 3) 加密数据。 docs.microsoft.com/en-us/dotnet/api/…
  • @jdweng:你只是在混淆事情。这不是公钥(非对称)加密的实例,因此不涉及公钥和私钥。
  • 密文只能在我的机器上用melloware fork的Jasypt版本解密,original versions不行。似乎实现方式不同。

标签: java c# encryption .net-core


【解决方案1】:

发布的密文长度为 32 字节,明文长度为 5 字节(或 8 字节,包括填充)。根据 Jasypt 源代码,连接按 salt | 的顺序进行。四 |密文,其中盐为 8 个字节长,IV 为 16 个字节。
16 字节长的 IV 在块大小为 8 字节的 TripleDES 的上下文中没有意义,并且在解密期间根本不使用。换句话说,密文中的IV可以被任何16字节序列替换,解密后的明文仍然是一样的。


所以对于解密盐,IV和密文必须分开,IV可以被丢弃。

密钥/IV派生函数的描述已经发布在问题中。一个实现示例如下所示:

private static byte[] GetKeyIV(String password, byte[] salt, int count)
{
    // Decode passwort
    byte[] pwd = Encoding.UTF8.GetBytes(password);

    // Split salt in 2 parts
    byte[] salt1 = new byte[4];
    byte[] salt2 = new byte[4];
    Array.Copy(salt, 0, salt1, 0, salt1.Length);
    Array.Copy(salt, 4, salt2, 0, salt2.Length);

    // Reverse 1st part if both parts are equal
    if (salt1.SequenceEqual(salt2))
    {
        Array.Reverse(salt1, 0, salt1.Length);
    }

    // Calculate 1st hash
    byte[] hash1 = salt1;
    for (int i = 0; i < count; i++)
    {
        MD5 md = MD5.Create();
        hash1 = md.ComputeHash(Concatenate(hash1, pwd));
    }

    // Calculate 2nd hash
    byte[] hash2 = salt2;
    for (int i = 0; i < count; i++)
    {
        MD5 md = MD5.Create();
        hash2 = md.ComputeHash(Concatenate(hash2, pwd));
    }

    // Join both hashes
    return Concatenate(hash1, hash2);
}

private static byte[] Concatenate(byte[] arr1, byte[] arr2)
{
    byte[] bytes = new byte[arr1.Length + arr2.Length];
    Buffer.BlockCopy(arr1, 0, bytes, 0, arr1.Length);
    Buffer.BlockCopy(arr2, 0, bytes, arr1.Length, arr2.Length);
    return bytes;
}

使用前 24 个字节作为 TripleDES 的密钥,使用最后 8 个字节作为 IV。

这允许使用通常的 MS 模式进行解密:

// Separate data
byte[] data = Convert.FromBase64String("7bALjokBDuxopB+Z37DwiTX/jg3/pjUoKW4q25uzd34=");
byte[] salt = new byte[8];
byte[] ciphertext = new byte[data.Length - salt.Length - 16];
Array.Copy(data, 0, salt, 0, salt.Length);
Array.Copy(data, salt.Length + 16, ciphertext, 0, ciphertext.Length);

// Derive key and IV
byte[] keyIV = GetKeyIV("17EXGCnC", salt, 1000); // count = 1000 according to Jasypt sources
byte[] key = new byte[24];
byte[] iv = new byte[8];
Array.Copy(keyIV, 0, key, 0, key.Length);
Array.Copy(keyIV, key.Length, iv, 0, iv.Length);

// Decrypt
string plaintext = "";
using (TripleDESCryptoServiceProvider aesAlg = new TripleDESCryptoServiceProvider())
{
    aesAlg.Key = key;
    aesAlg.IV = iv;
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
    using (MemoryStream msDecrypt = new MemoryStream(ciphertext))
    {
        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        {
            using (StreamReader srDecrypt = new StreamReader(csDecrypt))
            {
                plaintext = srDecrypt.ReadToEnd();
            }
        }
    }
}
Console.WriteLine(plaintext);

给出Java代码的结果:-1,-1


请注意,PBEWithMD5AndTripleDES 是一种过时的算法,仅应出于兼容性原因使用。
使用 MD5 的密钥派生不是很安全,而且 1000 的迭代次数太少。相反,应该使用更可靠的密钥派生函数,例如 PBKDF2。
TripleDES 也已过时且性能不佳,应由更现代的算法(如 AES)取代。

【讨论】:

  • 你是最棒的。谢谢!根据您的代码实现加密方法也很容易。加密没那么重要。它用于向客户端发送一个密钥,其中隐藏了两个 id,他们在另一个请求中使用该密钥来获取数据。我不知道他们为什么选择这个解决方案,而不是仅仅接受请求中的 id,但我需要向后兼容,因为客户端现在有了密钥,我需要能够向他们发送正确的数据。
猜你喜欢
  • 1970-01-01
  • 2020-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 2018-08-26
  • 1970-01-01
相关资源
最近更新 更多