【问题标题】:Java TripleDES PKCS5Padding decryption to C# - bad data / padding errorJava TripleDES PKCS5Padding 解密到 C# - 坏数据/填充错误
【发布时间】:2017-08-14 20:57:20
【问题描述】:

我正在尝试为以下 Java 代码编写 C# 等效代码:

protected static final String DES_ECB_PKCS5PADDING = "DESede/ECB/PKCS5Padding";

 public static String decryptValueDirect(String value, String key)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            GeneralSecurityException, IllegalBlockSizeException,
            BadPaddingException {
        byte[] bytes = Base64.decodeBase64(value);
        Cipher cipher = Cipher.getInstance(DES_ECB_PKCS5PADDING);
        cipher.init(Cipher.DECRYPT_MODE, convertSecretKey(key.getBytes()));
        byte[] decryptedValue = cipher.doFinal(bytes);

        String nstr =  new String(decryptedValue);
        return nstr;
    }
protected static SecretKey convertSecretKey(byte[] encryptionKey) throws GeneralSecurityException {
        if (encryptionKey == null || encryptionKey.length == 0)
            throw new IllegalArgumentException("Encryption key must be specified");

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(TRIPLEDES);
        KeySpec keySpec = new DESedeKeySpec(encryptionKey);
        return keyFactory.generateSecret(keySpec);
    }

源文本是一个 base64 编码,然后加密,然后是 base64 编码,以便在兔子队列上传输。我们处理加密的供应商提供了上述用于在 Java 中解密的内容,但对 C# 一无所知。

加密端的唯一输入是一个密钥,一个随机字符串。我们在开发环境中使用相同的字符串进行加密/解密 012345678901234567890123456789。这是唯一的输入,没有盐、散列(我看到)或 pw 迭代。唯一的要求是长度至少为 24 个字符。

我的 C# 代码在下面,我尝试的 fiddle 在这里。

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class Program
{
    public static void Main()
    {
        //Message Data value
        //We are using encrypted multibyte.     
        string myData = @"ROE8oYeV7B6faUsvfIx0Xe55vSs9IR5DlWGRbSM+lmKmLcaJsA13VudwWlAEYtLUD8+nMXShky0grSxsk0Z9cQe5V45XnAIfUhnyzI9a0jtMFC8XnIZ5dbclPO/V73QnieIZDkbNV5cPo3BM+l79ai96KB/gkF3xuerFPxvWejtPyWbOyO+FfNyFps4gAYDITsYIAEH39VP4eipmQ5zc18BA39lajQ3UaVewSxz7H+x3Ooe2SzJT/TQWRkioJSEFwexqzkHiLOQ0MOCIVD9xTWpLYnsL3LMwyF6H8f0PY4Fc57LVGhvUZ7dsB9NWUAnmG3uqbsonNFVhuXyvJTWNyFOHwFzOMx6XDLJJFHGZhaHg2VrescfnpUtonQY08RgojBngyJNRqK8URAvI3bqKq8Y7F/9HmEtMIIQe6KuuTmU=";
        string myKey = "012345678901234567890123456789";//Development Env Key.
        Console.WriteLine("Decrypt1:");
        string s = Decrypt1(myData, myKey);
        Console.ReadLine();
    }

    public static string Decrypt1(string value, string decryptionKey)
    {
        string decryptString = "";
        TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();
        MD5CryptoServiceProvider hashMD5Provider = new MD5CryptoServiceProvider();
        try
        {
            byte[] decodedData = Convert.FromBase64String(value);
            tDESalg.Mode = CipherMode.ECB;
            tDESalg.Padding = PaddingMode.PKCS7;//According to MS, same as PKCS5PADDING

            byte[] Key = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(decryptionKey));
            //byte[] IV = tDESalg.IV;
            byte[] IV = new byte[tDESalg.BlockSize / 8]; //The size of the IV property must be the same as the BlockSize property divided by 8

            var memoryStream = new MemoryStream(decodedData);
            var cryptoStream = new CryptoStream(memoryStream, tDESalg.CreateDecryptor(Key, IV), CryptoStreamMode.Read);
            var reader = new StreamReader(cryptoStream);
            decryptString = reader.ReadToEnd();
            byte[] decryptData = Convert.FromBase64String(decryptString);
        }
        catch (Exception e)
        {
            Console.WriteLine("A Cryptographic error occurred: {0}", e.Message + e.StackTrace);
            return null;
        }

        return decryptString;
    }

}

搜索似乎指向同一个答案,密钥、编码……都必须相同。我只是不知道所提供的 Java 源代码是什么等价物。 :) 任何建议都会有所帮助。

【问题讨论】:

  • 如果您的代码有问题,那么您应该提供一个Minimal, Complete, and Verifiable example 来证明您的问题。帮助我们帮助您,而不会浪费时间猜测。另外,不要提供指向您的代码的链接。相反,edit 你的问题包括代码。链接总是断开,如果断开,这个问题将失去所有价值。
  • 当然你意识到 3DES 和 ECB 模式是一个糟糕的安全选择。
  • 嗯,密钥以一种有缺陷的方式解码,损失了一半的熵。但是,要在 C# 中获得相同的效果,只需丢弃密钥的最后 8 个字符,并以相同的方式解码,使用 Encoding.UTF8.GetBytes(),而不是使用 MD5。
  • @JamesKPolk 您似乎认为密钥不是十六进制表示。它更像是 2 键 3DES 密钥的十六进制表示,有时称为 2TDEA。
  • 我认为它应该是十六进制表示,但解码错误。如果 C# 必须匹配有缺陷的 Java 代码,我将展示如何做到这一点。当然,如果可能的话,最好不要做错。

标签: encryption cryptography tripledes


【解决方案1】:

MD5 有一个 16 字节的输出,三重 DES (3DES) 需要一个 24 字节的密钥。密钥大小不匹配。

C# 和 Java 密钥派生有很大不同:

C#:
byte[] Key = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(decryptionKey));
返回 16 字节。

Java:
SecretKeyFactory.getInstance(TRIPLEDES)
返回 24 字节。

有一个密钥选项 (2TDEA),其中使用 16 字节密钥,前 8 字节将被复制以创建最后 8 字节。 NIST 已弃用此选项。

一些实现将接受 16 字节的密钥并将密钥扩展到 24 字节,而有些则不会。您应该向 3DES 提供所有 24 字节,不要依赖实现来创建 24 字节密钥。

注意:问题已更新,因此不清楚实际的加密密钥是派生的。

【讨论】:

  • 以上是对詹姆斯评论的一个很好的解释。我按照上面的 James K Polk 所写的内容进行了更改:从此: byte[] Key = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(decryptionKey));为此: byte[] Key = Encoding.UTF8.GetBytes(decryptionKey.Substring(0,24)); 现在它可以正常工作了。谢谢 Zaph 和@James K Polk
猜你喜欢
  • 2023-04-07
  • 2021-03-15
  • 2021-01-09
  • 2017-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-21
相关资源
最近更新 更多