繁体   English   中英

解密 .net 中的 PBEWithMD5AndTripleDES 加密字符串

[英]decrypt PBEWithMD5AndTripleDES encrypted string in .net

我需要使用使用 PBEWithMD5AndTripleDES 算法的 org.jasypt.util.text.StrongTextEncryptor 解密在 Java 中生成的字符串。 I think I have found the source code here: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndTripleDESCipher.java

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

  1. 创建随机盐并将其分成两半。 如果两半相同,则反转其中之一。
  2. 将密码与每一半连接起来。
  3. 使用 c 迭代来消化每个连接,其中 c 是迭代计数。 将每个摘要轮的 output 与密码连接起来,并将结果用作下一个摘要操作的输入。 摘要算法是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中使用的package: https://mvnrepository.com/artifact/com.melloware/jasypt。

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


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

密钥/IV 推导 function 的描述已经发布在问题中。 一个实现示例如下所示:

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;
}

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

这允许使用通常的 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 的迭代次数太少。 相反,应该使用更可靠的密钥派生 function,例如 PBKDF2。
TripleDES 也已过时且性能不佳,应由更现代的算法(如 AES)取代。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM