杰瑞科技汇

Java如何DES解密C语言加密的数据?

下面我将提供一个完整、可运行的 C# 加密和 Java 解密的示例,并详细解释关键步骤和注意事项,以确保它们能够正确配合工作。

核心原则

要实现 C# 和 Java 之间的 DES 加密解密,必须确保以下四个方面在两端完全一致:

  1. 算法: DES (在 Java 中通常写作 DES/CBC/PKCS5Padding)。
  2. 密钥: 必须是 8 字节(64 位)的原始字节数组,两端需要使用完全相同的密钥。
  3. 初始化向量: 必须是 8 字节的原始字节数组,两端需要使用完全相同的 IV。IV 不需要保密,但必须与加密时使用的 IV 完全一致。
  4. 加密模式与填充: 通常使用 CBC 模式和 PKCS5PaddingPKCS7Padding(对于 DES,两者效果相同)。

第一步:C# 加密代码

我们将创建一个 C# 控制台应用程序来执行加密。

创建 C# 项目

使用 Visual Studio 或 dotnet new console 创建一个新的 C# 控制台项目。

编写 C# 加密代码

Program.cs 文件中,粘贴以下代码。

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public class CSharpEncryptor
{
    // 必须是8字节 (64位) 的密钥
    private static readonly byte[] Key = Encoding.UTF8.GetBytes("12345678"); // 示例密钥,请替换为你自己的密钥
    // IV 也必须是8字节,对于CBC模式,它和密钥同样重要
    private static readonly byte[] IV = Encoding.UTF8.GetBytes("abcdefgh"); // 示例IV,请替换为你自己的IV
    public static byte[] Encrypt(string plainText)
    {
        // 使用 DES 算法,CBC 模式,PKCS7 填充
        using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
        {
            des.Key = Key;
            des.IV = IV;
            des.Mode = CipherMode.CBC;
            des.Padding = PaddingMode.PKCS7;
            // 创建加密器
            ICryptoTransform encryptor = des.CreateEncryptor(des.Key, des.IV);
            // 将明文转换为字节数组
            byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
            // 使用 MemoryStream 和 CryptoStream 进行加密
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    cs.Write(plainBytes, 0, plainBytes.Length);
                    cs.FlushFinalBlock();
                }
                // 返回加密后的字节数组
                return ms.ToArray();
            }
        }
    }
    public static void Main(string[] args)
    {
        string originalText = "这是一段需要加密的秘密信息,Hello, World!";
        Console.WriteLine("原始文本: " + originalText);
        // 加密
        byte[] encryptedBytes = Encrypt(originalText);
        // 为了方便传输,通常将字节数组转换为 Base64 字符串
        string encryptedBase64 = Convert.ToBase64String(encryptedBytes);
        Console.WriteLine("加密后的 Base64 字符串: " + encryptedBase64);
        // 将这个 Base64 字符串传递给 Java 程序进行解密
        // 你可以将它保存到文件或通过网络发送
        File.WriteAllText("encrypted_data.txt", encryptedBase64);
        Console.WriteLine("加密数据已保存到 encrypted_data.txt");
    }
}

C# 代码要点:

  • DESCryptoServiceProvider 是 C# 中实现 DES 算法的标准类。
  • 我们显式设置了 Mode = CipherMode.CBCPadding = PaddingMode.PKCS7
  • 加密结果是一个 byte[],我们使用 Convert.ToBase64String 将其转换为字符串,这样可以方便地在文本文件或网络中传输。

第二步:Java 解密代码

我们创建一个 Java 程序来读取 C# 生成的加密文件并解密它。

创建 Java 项目

使用你喜欢的 IDE(如 IntelliJ IDEA, Eclipse)或命令行创建一个新的 Java 项目。

编写 Java 解密代码

在主类中,粘贴以下代码。

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
public class JavaDecryptor {
    // C# 端使用的密钥和 IV,必须完全一致
    private static final String KEY = "12345678"; // 8 bytes
    private static final String IV = "abcdefgh";  // 8 bytes
    public static String decrypt(String encryptedBase64) throws Exception {
        // 1. 准备密钥和 IV
        // SecretKeySpec 需要 key 的字节数组
        SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(StandardCharsets.UTF_8), "DES");
        // IvParameterSpec 需要 IV 的字节数组
        IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8));
        // 2. 创建 Cipher 实例
        // "DES/CBC/PKCS5Padding" 是 Java 中描述算法的标准格式
        // DES: 算法
        // CBC: 加密模式
        // PKCS5Padding: 填充方式
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        // 3. 初始化 Cipher 为解密模式
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        // 4. 解密
        // Base64 解码
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64);
        // 执行解密
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        // 5. 将解密后的字节数组转换回字符串
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }
    public static void main(String[] args) {
        try {
            // 从 C# 生成的文件中读取加密数据
            String encryptedBase64 = new String(Files.readAllBytes(Paths.get("encrypted_data.txt")));
            System.out.println("从文件读取的加密 Base64 字符串: " + encryptedBase64);
            // 解密
            String decryptedText = decrypt(encryptedBase64);
            System.out.println("解密后的文本: " + decryptedText);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("解密过程中发生错误: " + e.getMessage());
        }
    }
}

Java 代码要点:

  • Cipher.getInstance("DES/CBC/PKCS5Padding") 是关键,这个字符串明确指定了算法、模式和填充,必须与 C# 端的逻辑完全对应。
  • SecretKeySpecIvParameterSpec 分别用于包装密钥和 IV。
  • Java 8+ 使用 java.util.Base64 进行 Base64 编码/解码,这与 C# 的 Convert.ToBase64String 兼容。
  • cipher.init(Cipher.DECRYPT_MODE, ...)Cipher 对象设置为解密模式。

第三步:运行和验证

  1. 运行 C# 程序:

    • 执行 CSharpEncryptor
    • 它会在控制台打印出加密后的 Base64 字符串,并在项目根目录下创建一个名为 encrypted_data.txt 的文件,内容就是这个 Base64 字符串。
  2. 运行 Java 程序:

    • 确保你的 Java 项目可以访问到 encrypted_data.txt 文件(通常将它放在与 Java 源代码相同的目录下,或者指定正确的路径)。
    • 执行 JavaDecryptor
    • 它会读取 encrypted_data.txt,解密其中的内容,并在控制台打印出原始的明文。

如果一切配置正确,你将在 Java 的控制台看到与 C# 程序原始文本完全相同的内容。

常见问题与排查

如果解密失败(抛出 BadPaddingExceptionIllegalBlockSizeException),请按以下顺序检查:

  1. 密钥: 确保 C# 和 Java 中的 KEY 字符串完全相同,并且长度为 8 个字符。
  2. IV: 确保 C# 和 Java 中的 IV 字符串完全相同,并且长度为 8 个字符。
  3. 填充: 确保 C# 的 PaddingMode.PKCS7 和 Java 的 PKCS5Padding 匹配,对于 DES,它们是等价的。
  4. 模式: 确保 C# 的 CipherMode.CBC 和 Java 的 CBC 匹配。
  5. Base64: 确保 Java 正确读取了 C# 写入的 Base64 字符串,没有多余的空格或换行符。File.WriteAllText 通常是安全的,但如果手动处理,请小心。
  6. 编码: 明文和密钥/IV 的编码(C# 和 Java 都使用 UTF-8)必须一致。

安全性警告

  • DES 算法已经过时:它的密钥长度(56位)太短,很容易被暴力破解。绝对不要在新的、对安全性有要求的系统中使用 DES。
  • 此示例仅用于演示跨语言加密解密的原理。
  • 在实际应用中,请考虑使用更安全的算法,如 AES(高级加密标准),AES 的实现原理与 DES 类似,只需将算法名称、密钥长度等参数更换即可。
分享:
扫描分享到社交APP
上一篇
下一篇