C#实现CryptoJS结合MD5、SHA256的AES加密结果不匹配排查
加密结果不一致的核心问题根源
两边的差异完全出在密钥生成阶段的字节流构造逻辑错位,具体有两处不匹配:
- 第一层SHA256输入构造错误
C#当前实现是直接将MD5计算的原始字节,与第一份盐值12345678的UTF8字节做拼接,作为SHA256的输入。但CryptoJS中MD5()返回的是WordArray类型,与字符串做+拼接时会自动调用toString()方法,默认转换为小写十六进制字符串后再与盐值拼接,最终对拼接后的字符串做UTF8编码得到SHA256输入。两者的输入字节流完全不同,算出的第一层SHA256结果自然与CryptoJS端不匹配。 - 最终AES密钥的SHA256输入构造错误
C#当前实现是直接将第一层SHA256的原始字节,与第二份盐值01234567890123456的UTF8字节做拼接,作为最终SHA256的输入。但CryptoJS中,第一层SHA256的返回值同样是WordArray类型,与字符串拼接时也会自动转成小写十六进制字符串,再与第二份盐值拼接,最终对拼接后的字符串做UTF8编码得到SHA256结果,也就是AES密钥。这里的输入同样与CryptoJS端错位,最终生成的AES密钥本身就是错误的,导致加密结果完全不符。
修正后的C#实现
直接将密钥生成阶段的字节拼接逻辑,替换为与CryptoJS一致的“十六进制字符串拼接”逻辑即可,后续AES加密部分的ECB模式、无填充配置、密文转小写Hex的逻辑均无需修改:
internal static string EncryptPassword() { using (AesManaged aes = new AesManaged()) { var password = "12345"; // 计算密码MD5原始字节,与CryptoJS端逻辑一致 var passwordMd5 = ComputeMD5(password); // 将MD5结果转为小写十六进制字符串,匹配CryptoJS的WordArray toString()默认行为 var passwordMd5Hex = BitConverter.ToString(passwordMd5).Replace("-", "").ToLower(); // 拼接MD5 Hex与第一份盐值,计算第一层SHA256 var firstShaInput = passwordMd5Hex + "12345678"; var firstShaResult = ComputeSha256(firstShaInput); // 将第一层SHA256结果转为小写十六进制字符串,拼接第二份盐值后计算最终AES密钥 var firstShaResultHex = BitConverter.ToString(firstShaResult).Replace("-", "").ToLower(); var finalShaInput = firstShaResultHex + "01234567890123456"; var passwordKey = ComputeSha256(finalShaInput); // AES加密逻辑保持不变 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; } }
修正后运行即可得到与CryptoJS端完全一致的结果c3de82e9e8a28a4caded8c2ef0d49c80,原实现中用于字节拼接的CombineByteArray方法在修正后的逻辑中不再需要使用。
内容的提问来源于stack exchange,提问作者derodevil
相关产品推荐
相关产品推荐

