三重DES加密C# – 用Java解密

我从客户端服务器获取一个Triple DES解密字符串,该字符串已用c#编码(见下文):

using System.IO; using System; using System.Security.Cryptography; using System.Collections; using System.Text; class Program { static void Main() { Console.WriteLine("Hello, World!"); var encryption = TripleDESEncrypt("12345678901234", "C9AF269DF8A78A06D1216BFFF8F0536A"); Console.WriteLine(encryption); } public static string TripleDESEncrypt(string strClearText, string strKey) { byte[] bytClearText; byte[] bytClearTextChunk = new byte[8]; byte[] bytEncryptedChunk = new byte[8]; int BytesCount = 0; int nArrayPosition = 0; string strEncryptedChar; string strEncryptedText = ""; ArrayList Input = new ArrayList(); ArrayList Output = new ArrayList(); TripleDESCryptoServiceProvider tdes = (TripleDESCryptoServiceProvider)TripleDESCryptoServiceProvider.Create(); tdes.Key = HexToByteArray(strKey); tdes.Mode = CipherMode.ECB; ICryptoTransform tdesEncrypt = tdes.CreateEncryptor(); bytClearText = ASCIIEncoding.ASCII.GetBytes(strClearText); BytesCount = bytClearText.Length; for (int i = 0; i < BytesCount; i++) { if (nArrayPosition == 8) { Input.Add(bytClearTextChunk); bytClearTextChunk = new byte[8]; nArrayPosition = 0; } bytClearTextChunk[nArrayPosition] = bytClearText[i]; nArrayPosition++; } if (nArrayPosition != 0) Input.Add(bytClearTextChunk); foreach (byte[] Cbyte in Input) { tdesEncrypt.TransformBlock(Cbyte, 0, 8, bytEncryptedChunk, 0); Output.Add(bytEncryptedChunk); bytEncryptedChunk = null; bytEncryptedChunk = new byte[8]; } foreach (byte[] Cbyte in Output) { foreach (byte BByte in Cbyte) { strEncryptedChar = BByte.ToString("X"); strEncryptedChar = strEncryptedChar.PadLeft(2, Convert.ToChar("0")); strEncryptedText += strEncryptedChar; } } return strEncryptedText; } private static byte[] HexToByteArray(string strHex) { byte[] bytArray = new byte[strHex.Length / 2]; int positionCount = 0; for (int i = 0; i < strHex.Length; i += 2) { bytArray[positionCount] = byte.Parse(strHex.Substring(i, 2), System.Globalization.NumberStyles.HexNumber); positionCount++; } return bytArray; } } 

然后我尝试使用此密钥在Java中解密它: C9AF269DF8A78A06D1216BFFF8F0536A

这是我的解密代码:

 public String DesDecryptPin(String pin, String encryptKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException { String UNICODE_FORMAT = "UTF8"; String decryptedPinText = null; byte[] hexConvert = hexStringtoByteArray(encryptKey); SecretKey desKey = null; byte[] tdesKey = new byte[24]; System.arraycopy(hexConvert, 0, tdesKey, 0,16); System.arraycopy(hexConvert, 0, tdesKey, 0,8); byte[] encryptKeyBytes = encryptKey.getBytes(UNICODE_FORMAT); KeySpec desKeySpec = new DESedeKeySpec(tdesKey); Cipher desCipher; SecretKeyFactory skf = SecretKeyFactory.getInstance("DESede"); desCipher = Cipher.getInstance("DESede/ECB/NoPadding"); try { desKey = skf.generateSecret(desKeySpec); } catch (InvalidKeySpecException e) { e.printStackTrace(); } desCipher.init(Cipher.DECRYPT_MODE, desKey); byte[] decryptPin = desCipher.doFinal(pin.getBytes()); decryptedPinText = new String(decryptPin, "UTF-8"); return decryptedPinText; } 

输出/输出的样本输出将是"12345678901234"但是,我得到了混乱的废话,例如 0 8 /0

因此,在c#和java之间迷失了一些东西…这是我在此问过的上一个问题的后续内容

我很感激这方面的帮助

更改代码

  public String DesDecryptPin(String pin, String encryptKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException { String UNICODE_FORMAT = "UTF8"; String decryptedPinText = null; SecretKey desKey = null; byte[] encryptKeyBytes = EncodingUtils.getAsciiBytes(encryptKey); byte[] tdesKey = new byte[24]; System.arraycopy(encryptKeyBytes, 8, tdesKey, 0, 8); System.arraycopy(encryptKeyBytes, 0, tdesKey, 8, 16); KeySpec desKeySpec = new DESedeKeySpec(tdesKey); Cipher desCipher; SecretKeyFactory skf = SecretKeyFactory.getInstance("DESede"); desCipher = Cipher.getInstance("DESede/ECB/NoPadding"); try { desKey = skf.generateSecret(desKeySpec); } catch (InvalidKeySpecException e) { e.printStackTrace(); } desCipher.init(Cipher.DECRYPT_MODE, desKey); byte[] decryptPin = desCipher.doFinal(EncodingUtils.getAsciiBytes(pin)); decryptedPinText = new String(decryptPin, "ASCII"); return decryptedPinText; } 

c#解密代码

 using System.IO; using System; using System.Security.Cryptography; using System.Collections; using System.Text; class Program { static void Main() { Console.WriteLine("Hello, World!"); var encryption = TripleDESDecrypt("1D30CC3DE1641D7F5E821D13FC1200C3", "C9AF269DF8A78A06D1216BFFF8F0536A"); Console.WriteLine(encryption); } public static string TripleDESDecrypt(string strEncryptedText, string strKey) { string errorMessage = ""; int errorCode = 0; string strDecryptedText = ""; try { byte[] bytEncryptedChunk = new byte[8]; byte[] bytClearTextChunk = new byte[8]; byte[] _bytesEmpty = new byte[8]; int BytesCount = 0; int positionCount = 0; ArrayList Input = new ArrayList(); ArrayList Output = new ArrayList(); TripleDESCryptoServiceProvider tdes = (TripleDESCryptoServiceProvider)TripleDESCryptoServiceProvider.Create(); tdes.Key = HexToByteArray(strKey); tdes.Mode = CipherMode.ECB; ICryptoTransform tdesDecrypt = tdes.CreateDecryptor(); BytesCount = strEncryptedText.Length; for (int i = 0; i < BytesCount; i += 2) { if (positionCount == 8) { positionCount = 0; Input.Add(bytEncryptedChunk); bytEncryptedChunk = new byte[8]; } bytEncryptedChunk[positionCount] = byte.Parse(strEncryptedText.Substring(i, 2), System.Globalization.NumberStyles.HexNumber); positionCount++; } if (positionCount != 0) { Input.Add(bytEncryptedChunk); } foreach (byte[] Cbyte in Input) { tdesDecrypt.TransformBlock(Cbyte, 0, 8, _bytesEmpty, 0); tdesDecrypt.TransformBlock(Cbyte, 0, 8, bytClearTextChunk, 0); Output.Add(bytClearTextChunk); bytClearTextChunk = null; bytClearTextChunk = new byte[8]; } foreach (byte[] Cbyte in Output) { strDecryptedText += ASCIIEncoding.ASCII.GetString(Cbyte); } } catch (Exception ex) { errorCode = 1; errorMessage = ex.Message; } Console.WriteLine(strDecryptedText); return strDecryptedText; } private static byte[] HexToByteArray(string strHex) { byte[] bytArray = new byte[strHex.Length / 2]; int positionCount = 0; for (int i = 0; i < strHex.Length; i += 2) { bytArray[positionCount] = byte.Parse(strHex.Substring(i, 2), System.Globalization.NumberStyles.HexNumber); positionCount++; } return bytArray; } } 

这将返回输入加密12345678901234的内容

在您的C#代码中,您使用ASCII:

 bytClearText = ASCIIEncoding.ASCII.GetBytes(strClearText); 

在Java中使用UNICODE:

 byte[] encryptKeyBytes = encryptKey.getBytes(UNICODE_FORMAT); 

尝试更改您的C#以使用UNICODE或您的Java代码来使用ASCII。

此外,由于C#填充输出:

 strEncryptedChar = strEncryptedChar.PadLeft(2, Convert.ToChar("0")); 

您可能必须检查以删除加密字符串中的所有’00’,因此1D30CC3DE1641D7F5E821D13FC12 00 C3将成为1D30CC3DE1641D7F5E821D13FC12C3

(你必须检查它是否在hex表达式的边界内:1C01A1应该被修改,因为它在第二个Hexa 1C上有填充0 1 A1:1C1A1

根据https://stackoverflow.com/a/33768305/1140304你可以在java代码中使用unicode而不是UTF-8

在c#中加密:

 public static string Encrypt2(string clearText,string key) { try { 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()); } return encryptedText; } catch (Exception exception) { return ""; } } 

在c#中解码你可以使用:

 public static string Decrypt2(string cipher,string key) { try { byte[] clearBytes = Convert.FromBase64String(cipher); MD5 md5 = new MD5CryptoServiceProvider(); byte[] md5Bytes = md5.ComputeHash(Encoding.Unicode.GetBytes(key)); string encryptedText = ""; TripleDES des = new TripleDESCryptoServiceProvider(); des.KeySize = 128; des.Mode = CipherMode.CBC; des.Padding = PaddingMode.PKCS7; byte[] ivBytes = new byte[8]; des.Key = md5Bytes; des.IV = ivBytes; ICryptoTransform ct = des.CreateDecryptor(); byte[] resultArray = ct.TransformFinalBlock(clearBytes, 0, clearBytes.Length); encryptedText = Encoding.Unicode.GetString(resultArray); return encryptedText; } catch (Exception exception) { return ""; } } 

现在,对于java中的加密,您可以使用:

 private String _encrypt2(String clearText,String key ) { try { /** * create md5 */ MessageDigest md = MessageDigest.getInstance("md5"); byte[] digestOfPassword = md.digest(key.getBytes("UTF-16LE")); byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); 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.encodeToString(cipherText,Base64.DEFAULT); return output; } catch (Exception ex) {} return ""; } 

并在java中解密:

 private String _decrypt2(String encryptText,String key) { MessageDigest md = null; byte[] digestOfPassword = null; try { byte[] message = Base64.decode(encryptText.getBytes("UTF-16LE"), Base64.DEFAULT); /** * make md5 */ md = MessageDigest.getInstance("md5"); digestOfPassword = md.digest(key.getBytes("UTF-16LE")); byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); 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.DECRYPT_MODE, secretKey, iv); byte[] cipherText = cipher.doFinal(message); return new String(cipherText, "UTF-16LE"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } return ""; }