You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java DES解密代码转C#实现的密钥与填充问题咨询

DES解密:Java到C#的移植问题

问题描述

我有一段Java的DES解密代码:

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#,但不清楚Java中SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(key))这部分的逻辑怎么处理。我当前的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字节。查DESKeySpec文档知道它会取前8字节作为密钥,但按这个处理后代码因填充错误崩溃,求正确的处理方式。

解决方案

问题核心是Java和C#默认的DES工作模式、填充模式不一致,加上密钥处理的细节差异,具体修复步骤如下:

  1. 对齐Java的密钥处理逻辑
    Java的DESKeySpec会直接取密钥字节数组的前8个字节,但注意Java中new String(keyString).getBytes()默认使用平台默认编码(通常为UTF-8,旧环境可能是GBK),C#中需使用相同编码获取字节数组后截取前8字节:

    // 若Java端用的不是UTF-8,替换为对应编码,比如Encoding.GetEncoding("GBK")
    byte[] keyBytes = Encoding.UTF8.GetBytes(keyString);
    // 截取前8字节作为DES密钥
    byte[] desKey = keyBytes.Take(8).ToArray();
    
  2. 对齐DES的工作模式与填充模式
    Java中Cipher.getInstance("DES")默认对应DES/ECB/PKCS5Padding,而C#的DESCryptoServiceProvider默认工作模式为CipherMode.CBC,这是导致填充错误的核心原因。需显式设置为ECB模式,填充模式用PKCS7(与Java的PKCS5Padding完全兼容):

    byte[] enc = Convert.FromBase64String(encryptedMessage);
    byte[] keyBytes = Encoding.UTF8.GetBytes(keyString);
    byte[] desKey = keyBytes.Take(8).ToArray();
    
    using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
    {
        des.Key = desKey;
        // 对齐Java默认工作模式:ECB
        des.Mode = CipherMode.ECB;
        // PKCS7与Java的PKCS5Padding兼容
        des.Padding = PaddingMode.PKCS7;
        
        ICryptoTransform desDecrypt = des.CreateDecryptor();
        byte[] result = desDecrypt.TransformFinalBlock(enc, 0, enc.Length);
        return Encoding.UTF8.GetString(result);
    }
    
  3. 额外排查要点

    • 确认Java端getBytes()使用的编码,若不是UTF-8必须同步修改C#的编码类型,否则密钥会不匹配
    • 若Java加密时使用了CBC模式,C#需同步设置CipherMode.CBC并指定相同的IV向量(Java默认会生成随机IV,但如果是固定IV需手动传入)
    • 不要吞掉异常,打印具体错误信息(如填充错误、密钥不匹配),便于快速定位问题

内容的提问来源于stack exchange,提问作者Luka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:27:51