我有以下代码,用于解密DES加密后的Java编码报文.

    try 
    {
        byte[] key = new String(keyString).getBytes();
        byte[] enc = Base64.getDecoder().decode(encryptedMessage);
        SecretKey generateSecret = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(key));
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(2, generateSecret);
        String dec = new String(cipher.doFinal(enc));
    }
    catch (Exception ex) 
    {
    }

我想把它移植到C#中.不过,我不确定如何处理SecretKey generateSecret = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(key));.下面是我用于DES解密的C#代码:

    byte[] enc = Convert.FromBase64String(encryptedMessage);
    byte[] key = Encoding.UTF8.GetBytes(keyString);

    using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
    {
        des.Key = key;
        ICryptoTransform desDecrypt = des.CreateDecryptor();
        byte[] result = desDecrypt.TransformFinalBlock(enc, 0, enc.Length);
        return Encoding.UTF8.GetString(result);
    }

我的值keyString超过30个字节,des.Key需要8个字节.在阅读new DESKeySpec()的文档时,我发现它占用了前8个字节.因此,我将这8个字节用作des.Key的键,代码崩溃并抱怨填充问题.所以,我意识到这不是处理这件事的方法.我不知道该如何处理这件事.非常感谢您的信息.

推荐答案

In the Java code, no mode is specified in Cipher.getInstance("DES"), so that the provider-dependent default value is used, which in the case of the SunJCE provider is ECB.
The C# code, on the other hand, uses the CBC mode by default, which must therefore be changed to ECB for compatibility with the Java code.
Padding is not a problem here, as the SunJCE provider and the C# side use PKCS#7 by default (which is called PKCS#5 in the Java world for historical reasons).

以下C#代码可以工作:

string keyString = "01234567890123456789012345678901";
string encryptedMessage = "gGSWHv6xiA3s2sr4aZzyA+g4fSGvnJ8NfxUiO6HMIazO+wJNy6dbdZK7KE0JcbyI";

byte[] enc = Convert.FromBase64String(encryptedMessage);
byte[] key = Encoding.UTF8.GetBytes(keyString)[0..8]; // get the first 8 bytes

using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
    des.Key = key;
    des.Mode = CipherMode.ECB; // choose ECB mode
    ICryptoTransform desDecrypt = des.CreateDecryptor();
    byte[] result = desDecrypt.TransformFinalBlock(enc, 0, enc.Length);
    Console.WriteLine(Encoding.UTF8.GetString(result)); // The quick brown fox jumps over the lazy dog
}

其中已经 Select 了测试数据,使得Java代码用密钥keyString解密密文encryptedMessage.


Note that it is advisable to specify the mode and padding explicitly on the Java side (e.g. Cipher.getInstance("DES/ECB/PKCS5Padding")) in order to remain unaffected by the provider-dependent default.
Likewise, the character set should be specified in the Java code when encoding and decoding (e.g. new String(cipher.doFinal(enc), StandardCharsets.UTF_8)), as otherwise the platform-dependent default is used.
Be aware that DES and ECB are insecure (DES has been deprecated for about 20 years, its successor is AES; more secure than ECB is CBC or even better authenticated encryption such as GCM).

Csharp相关问答推荐

EF Core Fluent API中定义的多对多关系

注册通用工厂的C# Dep注入

为什么我不能更改尚未设置的模拟对象属性的值?

有没有一种方法可以在包含混合文本的标签中嵌入超链接?

(乌龙)1&#比c#中的UL&#慢吗?

静态对象构造顺序

WinForms在Linux上的JetBrains Rider中的应用

C#中Java算法的类似功能

在两个已具有一对多关系的表之间添加另一个一对多关系

在C#中有没有办法减少大型数组中新字符串的分配?

如何在.NET MAUI中最大化GraphicsView的大小?

实体框架-IsRequired()与OnDelete()

为什么我在使用有效令牌的情况下仍未获授权?

C#;AvaloniaUI;MVVM;当另一个窗口上的按钮被单击时,如何更新视图图像源?

除非首先访问使用的终结点,否则本地API上的终结点不起作用

为什么Visual Studio 2022建议IDE0251将我的方法设置为只读?

如何根据分割文本的块数来计算文本的大小?

我想我必须手动使用res1(字符串形式的PowerShell哈希表)

无法将.Net Framework 4.8.1升级到.Net 7

Unity 3D-意外轴捕捉和未知力对脉冲react 行为的影响