简体   繁体   English

CryptoJS AES 加密在 C# 中使用 MD5 和 SHA256 未生成正确的值

[英]CryptoJS AES encryption with MD5 and SHA256 in C# not generated proper value

I want to encrypt password using both in CryptoJS and C#.我想同时在 CryptoJS 和 C# 中加密密码。 Unfortunately, my C# code fails to generate the proper value.不幸的是,我的 C# 代码无法生成正确的值。 This is my code这是我的代码

internal static byte[] ComputeSha256(this byte[] value)
{
    using (SHA256 sha256Hash = SHA256.Create())
        return sha256Hash.ComputeHash(value);
}

internal static byte[] ComputeSha256(this string value) => ComputeSha256(Encoding.UTF8.GetBytes(value));

internal static byte[] ComputeMD5(this byte[] value)
{
    using (MD5 md5 = MD5.Create())
        return md5.ComputeHash(value);
}

internal static byte[] ComputeMD5(this string value) => ComputeMD5(Encoding.UTF8.GetBytes(value));

internal static byte[] CombineByteArray(byte[] first, byte[] second)
{
    byte[] bytes = new byte[first.Length + second.Length];
    Buffer.BlockCopy(first, 0, bytes, 0, first.Length);
    Buffer.BlockCopy(second, 0, bytes, first.Length, second.Length);
    return bytes;
}
        
internal static string EncryptPassword()
{
    using (AesManaged aes = new AesManaged())
    {
            //CLIENT SIDE PASSWORD HASH
            /*
            var password = '12345';
            var passwordMd5 = CryptoJS.MD5(password);
            var passwordKey = CryptoJS.SHA256(CryptoJS.SHA256(passwordMd5 + '12345678') + '01234567890123456');
            var encryptedPassword = CryptoJS.AES.encrypt(passwordMd5, passwordKey, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
            encryptedPassword = CryptoJS.enc.Base64.parse(encryptedPassword.toString()).toString(CryptoJS.enc.Hex);
            //encryptedPassword result is c3de82e9e8a28a4caded8c2ef0d49c80
            */

            var y1 = Encoding.UTF8.GetBytes("12345678");
            var y2 = Encoding.UTF8.GetBytes("01234567890123456");
            var password = "12345";
            var passwordMd5 = ComputeMD5(password);

            var xkey = CombineByteArray(ComputeSha256(CombineByteArray(passwordMd5, y1)), y2);
            var passwordKey = ComputeSha256(xkey);

            aes.Key = passwordKey;
            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.None;
            ICryptoTransform crypt = aes.CreateEncryptor();
            byte[] cipher = crypt.TransformFinalBlock(passwordMd5, 0, passwordMd5.Length);
            var encryptedPassword = BitConverter.ToString(cipher).Replace("-", "").ToLower();
            return encryptedPassword; //e969b60e87339625c32f805f17e6f993
    }
}

The result of the C# code above is e969b60e87339625c32f805f17e6f993 .上面的 C# 代码的结果是e969b60e87339625c32f805f17e6f993 It should be the same with CryptoJS c3de82e9e8a28a4caded8c2ef0d49c80 .它应该与 CryptoJS c3de82e9e8a28a4caded8c2ef0d49c80相同。 What is wrong here?这里有什么问题?

In the CryptoJS code hashes (in the form of WordArray s) and strings are added in several places.在 CryptoJS 代码中,哈希(以WordArray的形式)和字符串被添加到几个地方。 Thereby the WordArray is implicitly encoded with toString() into a hex string with lowercase letters.因此, WordArray使用toString()隐式编码为带有小写字母的十六进制字符串。 This is missing in the C# code. C# 代码中缺少此内容。

In the C# code the addition is done with CombineByteArray() , where the hash is passed in the parameter first as byte[] .在 C# 代码中,添加是使用CombineByteArray()完成的,其中 hash first作为byte[]传入参数。 Therefore this parameter must first be converted to a hex encoded string with lowercase letters and then UTF8 encoded, eg:因此该参数必须先转换为小写字母的十六进制编码字符串,然后进行 UTF8 编码,例如:

internal static byte[] CombineByteArray(byte[] first, byte[] second)
{
    // Hex encode (with lowercase letters) and Utf8 encode
    string hex = ByteArrayToString(first).ToLower();
    first = Encoding.UTF8.GetBytes(hex);

    byte[] bytes = new byte[first.Length + second.Length];
    Buffer.BlockCopy(first, 0, bytes, 0, first.Length);
    Buffer.BlockCopy(second, 0, bytes, first.Length, second.Length);
    return bytes;
}

where ByteArrayToString() is from here . ByteArrayToString()来自这里

With this change, the C# code gives the same result as the CryptoJS code.通过此更改,C# 代码给出与 CryptoJS 代码相同的结果。


I am not quite clear about the purpose of the CryptoJS code.我不太清楚 CryptoJS 代码的用途。 Usually plaintext and key are independent, ie are not derived from the same password.通常明文和密钥是独立的,即不是来自同一个密码。
Perhaps this is supposed to implement a custom password-based key derivation function.也许这应该实现自定义的基于密码的密钥派生 function。 If so, and unless a custom implementation is mandatory for compatibility reasons, it is more secure to use a proven algorithm such as Argon2 or PBKDF2.如果是这样,并且除非出于兼容性原因必须使用自定义实现,否则使用经过验证的算法(例如 Argon2 或 PBKDF2)会更安全。 In particular, the lack of a salt/work factor is insecure.特别是,缺乏盐/工作因素是不安全的。

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

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