java - Java DES 加密,C# DES 解密
问题描述
我收到了来自 Java 的加密字符串,我可以看到 Java 加密的源代码。我用 C# 编写了解密代码。但是总是在“FlushFinalBlock”报错。错误消息:“System.Security.Cryptography.CryptographicException。附加信息:数据不正确。”
任何人都可以指出我的 C# 代码中的问题所在吗?
这是java代码:
private static byte[] coderByDES(byte[] plainText, String key, int mode)
throws InvalidKeyException, InvalidKeySpecException,
NoSuchAlgorithmException, NoSuchPaddingException,
BadPaddingException, IllegalBlockSizeException,
UnsupportedEncodingException {
SecureRandom sr = new SecureRandom();
byte[] resultKey = makeKey(key);
DESKeySpec desSpec = new DESKeySpec(resultKey);
SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(desSpec);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(mode, secretKey, sr);
return cipher.doFinal(plainText);
}
private static byte[] makeKey(String key)
throws UnsupportedEncodingException {
byte[] keyByte = new byte[8];
byte[] keyResult = key.getBytes("UTF-8");
for (int i = 0; i < keyResult.length && i < keyByte.length; i++) {
keyByte[i] = keyResult[i];
}
return keyByte;
}
private static String byteArr2HexStr(byte[] arrB) {
int iLen = arrB.length;
StringBuilder sb = new StringBuilder(iLen * 2);
for (int i = 0; i < iLen; i++) {
int intTmp = arrB[i];
while (intTmp < 0) {
intTmp = intTmp + 256;
}
if (intTmp < 16) {
sb.append("0");
}
sb.append(Integer.toString(intTmp, 16));
}
return sb.toString();
}
这是 C# 代码:
public static string DecryptForDES(string input, string key)
{
byte[] inputByteArray = HexStr2ByteArr(input);
byte[] buffArray = null;
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
des.Key = Encoding.UTF8.GetBytes(key);
des.IV = Encoding.UTF8.GetBytes(key);
des.Mode = System.Security.Cryptography.CipherMode.ECB;
des.Padding = PaddingMode.PKCS7;
System.IO.MemoryStream ms = new System.IO.MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();//
cs.Close();
}
buffArray = ms.ToArray();
ms.Close();
}
string str = string.Empty;
if (buffArray != null)
{
str = Encoding.UTF8.GetString(buffArray);
}
return str;
}
public static byte[] HexStr2ByteArr(string strIn)
{
byte[] arrB = Encoding.UTF8.GetBytes(strIn);
int iLen = arrB.Length;
byte[] arrOut = new byte[iLen / 2];
byte[] arrTmp = new byte[2];
for (int i = 0; i < iLen; i = i + 2)
{
string strTmp = Encoding.UTF8.GetString(arrB, i, 2);
arrOut[i / 2] = (byte)Convert.ToInt32(strTmp, 16);
}
return arrOut;
}
解决方案
如果密码匹配,Java 加密部分和 C# 解密部分都可以在我的机器上运行。否则会抛出 System.Security.Cryptography.CryptographicException: ' Bad Data'。在 C# 方法 DecryptForDES 中获取密码匹配替换
des.Key = Encoding.UTF8.GetBytes(key);
和
des.Key = MakeKey(key);
使用 C# 方法:
private static byte[] MakeKey(String key)
{
byte[] keyByte = new byte[8];
byte[] keyResult = Encoding.UTF8.GetBytes(key);
for (int i = 0; i<keyResult.Length && i<keyByte.Length; i++) {
keyByte[i] = keyResult[i];
}
return keyByte;
}
对应于 Java 方法 makeKey(String key)。此外,在 C# 方法 DecryptForDES 中删除
des.IV = Encoding.UTF8.GetBytes(key);
因为 ECB 模式不使用 IV。
在以下测试用例中
coderByDES("This is a plain text that needs to be encrypted...", "This is the key used for encryption...", Cipher.ENCRYPT_MODE);
返回字节数组
a47b1b2c90fb3b7a0ab1f51f328ff55aae3c1eb7789c31c28346696a8b1f27c7413c14e68fe977d3235b5a6f63c07d7a95d912ff22f17ad6
和
DecryptForDES("a47b1b2c90fb3b7a0ab1f51f328ff55aae3c1eb7789c31c28346696a8b1f27c7413c14e68fe977d3235b5a6f63c07d7a95d912ff22f17ad6", "This is the key used for encryption...");
返回正确的纯文本。
顺便说一句:正如 Flydog57 已经声明 DES 不安全(https://en.wikipedia.org/wiki/Data_Encryption_Standard)。而且 ECB 模式也不安全(https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption)。更好的选择是带有 CBC 或 GCM 模式的 AES ( https://en.wikipedia.org/wiki/Advanced_Encryption_Standard ) ( https://crypto.stackexchange.com/questions/2310/what-is-the-difference-between-cbc -和-gcm-模式)。
推荐阅读
- reactjs - 在 React 表中过滤日期列
- listview - Managing component state in NativeScript-Vue ListView
- python - 如何删除大型法语文本文件中的所有特殊字符
- grafana - How To Push Gatling Perf Results To EC2 Grafana/InfluxDB instance
- docker - Error w/ installing memcached in Docker alpine image
- php - 在 Laravel 中搜索 where 子句或 Where 子句
- css - p-listbox:搜索过滤器文本框不适合宽度
- python - 安装 JsonGraph 模块时出现编译错误
- javascript - 为什么通过实例调用“get 方法”不需要括号(分组运算符)?
- codeigniter-3 - DOM Input 元素应该具有自动完成属性