C#到Java TripleDES,结果不同

我正在尝试将此C#加密算法转换为Java; 但是,我一直在检索略有不同的加密结果(尚未尝试过解密)。 指出我无法更改C#代码也可能很重要。

但是当我在字符串“test”中调用C#中的加密函数时,它将返回nmj8MjjO52y928Syqf0J+g==但是在Java中它将返回C6xyQjJCqVo=

C#

 private static String key = "012345678901234567890123"; public static string encrypt(String stringToEncrypt) { TripleDES des = CreateDES(key); ICryptoTransform ct = des.CreateEncryptor(); byte[] input = Encoding.Unicode.GetBytes(stringToEncrypt); byte[] output = ct.TransformFinalBlock(input, 0, input.Length); //return output; return Convert.ToBase64String(output); } public static String decrypt(string encryptedString) { byte[] input = Convert.FromBase64String(encryptedString); TripleDES des = CreateDES(key); ICryptoTransform ct = des.CreateDecryptor(); byte[] output = ct.TransformFinalBlock(input, 0, input.Length); return Encoding.Unicode.GetString(output); } public static TripleDES CreateDES(string key) { MD5 md5 = new MD5CryptoServiceProvider(); TripleDES des = new TripleDESCryptoServiceProvider(); des.Key = md5.ComputeHash(Encoding.Unicode.GetBytes(key)); des.IV = new byte[des.BlockSize / 8]; return des; } 

我尝试转换为Java

 private static String key = "012345678901234567890123"; public static void main(String[] args) throws Exception { String text = "test"; String codedtext = encrypt(text); //String decodedtext = decrypt(codedtext); System.out.println(new String(codedtext)); //System.out.println(decodedtext); } public static String encrypt(String message) throws Exception { MessageDigest md = MessageDigest.getInstance("md5"); byte[] digestOfPassword = md.digest(key.getBytes("unicode")); byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); //for (int j = 0, k = 16; j < 8;) { // keyBytes[k++] = keyBytes[j++]; //} SecretKey key = new SecretKeySpec(keyBytes, "DESede"); IvParameterSpec iv = new IvParameterSpec(new byte[8]); Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key, iv); byte[] plainTextBytes = message.getBytes(); byte[] cipherText = cipher.doFinal(plainTextBytes); String output = Base64.encode(cipherText); return output; } public static String decrypt(String message) throws Exception { byte[] messageBytes = Base64.decode(message); MessageDigest md = MessageDigest.getInstance("md5"); byte[] digestOfPassword = md.digest(key.getBytes()); byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); for (int j = 0, k = 16; j < 8;) { keyBytes[k++] = keyBytes[j++]; } SecretKey key = new SecretKeySpec(keyBytes, "DESede"); IvParameterSpec iv = new IvParameterSpec(new byte[8]); Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); decipher.init(Cipher.DECRYPT_MODE, key, iv); byte[] plainText = decipher.doFinal(messageBytes); return new String(plainText); } 

有谁看到我在监督什么?

你错过了两件事。 您在c#端使用16长度密钥,因为它没有像Java版本那样填充。 默认情况下,如果密钥长度为16个字节,则将使用密钥的前8个字节填充。

要在Java端进行此匹配,您必须取消注释将该填充添加到键的行:

 for (int j = 0, k = 16; j < 8;) { keyBytes[k++] = keyBytes[j++]; } SecretKey secretKey = new SecretKeySpec(keyBytes, 0, 24, "DESede"); 

此外,在Java方面,有一个建议,以确保使用UTF-LE的文本。 确保将它用于一切。 所以线条:

 byte[] digestOfPassword = md.digest(key.getBytes("UTF-16LE")); byte[] plainTextBytes = clearText.getBytes("UTF-16LE"); 

一般来说,我会确保设置所有三元组对象的c#参数,而不是依赖于默认值。

以下是c#和java中匹配的两个版本

Java的

 String key = "012345678901234567890123"; String clearText = "test"; MessageDigest md = MessageDigest.getInstance("md5"); byte[] digestOfPassword = md.digest(key.getBytes("UTF-16LE")); byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); String byteText = Arrays.toString(keyBytes); for (int j = 0, k = 16; j < 8;) { keyBytes[k++] = keyBytes[j++]; } SecretKey secretKey = new SecretKeySpec(keyBytes, 0, 24, "DESede"); IvParameterSpec iv = new IvParameterSpec(new byte[8]); Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); byte[] plainTextBytes = clearText.getBytes("UTF-16LE"); byte[] cipherText = cipher.doFinal(plainTextBytes); String output = Base64.encode(cipherText); 

C#

 string clearText = "test"; string key = "012345678901234567890123"; string encryptedText = ""; MD5 md5 = new MD5CryptoServiceProvider(); TripleDES des = new TripleDESCryptoServiceProvider(); des.KeySize = 128; des.Mode = CipherMode.CBC; des.Padding = PaddingMode.PKCS7; byte[] md5Bytes = md5.ComputeHash(Encoding.Unicode.GetBytes(key)); byte[] ivBytes = new byte[8]; des.Key = md5Bytes; des.IV = ivBytes; byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); ICryptoTransform ct = des.CreateEncryptor(); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(clearBytes, 0, clearBytes.Length); cs.Close(); } encryptedText = Convert.ToBase64String(ms.ToArray()); } 

编辑:两个版本现在返回测试用例结果“nmj8MjjO52y928Syqf0J + g ==”