Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将DES加密数据从Java解密到.Net_C#_Java_Cryptography_Des - Fatal编程技术网

C# 将DES加密数据从Java解密到.Net

C# 将DES加密数据从Java解密到.Net,c#,java,cryptography,des,C#,Java,Cryptography,Des,我在解密使用DES算法在Java中加密的加密字符串时遇到问题。我认为我的主要问题是,我在java代码中没有看到任何salt或IV规范 我有以下资料: 这个十六进制序列是我必须解密的加密数据:9465E19A6B9060D75C3F725ED1FD4D21EDC18BB185304B92061308A32725BE760F1847E3B19C1D3548F61165EA2E785E48F61165EA2E78 算法:DES,Padding:DES/ECB/NoPadding,Key:TESTKEY

我在解密使用DES算法在Java中加密的加密字符串时遇到问题。我认为我的主要问题是,我在java代码中没有看到任何salt或IV规范

我有以下资料: 这个十六进制序列是我必须解密的加密数据:9465E19A6B9060D75C3F725ED1FD4D21EDC18BB185304B92061308A32725BE760F1847E3B19C1D3548F61165EA2E785E48F61165EA2E78

算法:DES,Padding:DES/ECB/NoPadding,Key:TESTKEY123

解密后我应该得到:550000000018H000000273AL201111221440600000000000000000000000

用于加密数据的java代码如下所示:

public class Encryptor {

private SecretKey secretKey;
private Cipher cipher;

public Encryptor(String algorithmName, String paddingName, String key) {
    String keyHexCode = StringUtils.convertUnicodeToHexCode(key.getBytes());
    try {
        byte[] desKeyData = StringUtils.convertHexStringToByteArray(keyHexCode);

        DESKeySpec desKeySpec = null;
        try {
            desKeySpec = new DESKeySpec(desKeyData);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithmName);
        try {
            secretKey = keyFactory.generateSecret(desKeySpec);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        try {
            cipher = Cipher.getInstance(paddingName);
        } catch (NoSuchPaddingException e) {
            // TODO: handle exception
        }
    } catch (NoSuchAlgorithmException e) {
        // TODO: handle exception
    }
}

private void initEncryptor(int mode) {
    try {
        cipher.init(mode, secretKey);
    } catch (InvalidKeyException e) {
        // TODO: handle exception
    }
}

public String encrypt(String clearText) {
    initEncryptor(Cipher.ENCRYPT_MODE);
    try {
        // Encrypt the cleartext
        byte[] encryptedBytes = cipher.doFinal(clearText.getBytes());
        return StringUtils.convertUnicodeToHexCode(encryptedBytes).toUpperCase();
    } catch (IllegalBlockSizeException e) {
        // TODO: handle exception
    } catch (BadPaddingException e) {
        // TODO: handle exception
    }
    return "";
}

public String decrypt(String encryptedTextHex) {
    byte[] encryptedText = StringUtils.convertHexCodeSequenceToUnicode(encryptedTextHex);
    initEncryptor(Cipher.DECRYPT_MODE);
    try {
        // Decrypt the encryptedTextHex
        return new String(cipher.doFinal(encryptedText));
    } catch (IllegalBlockSizeException e) {
        // TODO: handle exception
    } catch (BadPaddingException e) {
        // TODO: handle exception
    }
    return "";
}
}
我尝试使用以下.net代码解密数据:

public class URLDecryptor
{
public static string GetValue(string Data)
{
    DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
    byte[] bytes = System.Text.UnicodeEncoding.Unicode.GetBytes("TESTKEY123");
    byte[] salt = new byte[8];
    byte[] iv = new byte[8];
    Rfc2898DeriveBytes password = new Rfc2898DeriveBytes("TESTKEY123", salt);
    cryptoProvider.Key = password.GetBytes(8);
    cryptoProvider.IV = iv;
    cryptoProvider.Padding = PaddingMode.None;
    cryptoProvider.Mode = CipherMode.ECB;

    MemoryStream memStream = new MemoryStream(convertHexCodeSequenceToUnicode(Data));
    CryptoStream cryptoStream = new CryptoStream(memStream, cryptoProvider.CreateDecryptor(cryptoProvider.Key, cryptoProvider.IV), CryptoStreamMode.Read);
    StreamReader reader = new StreamReader(cryptoStream);
    string value = reader.ReadToEnd;

    reader.Close();
    cryptoStream.Close();

    return value;
}

private static byte[] convertHexCodeSequenceToUnicode(string hexCodeSequence)
{
    byte[] bytes = new byte[(hexCodeSequence.Length / 2) + 1]; //This is strange
    int index = 0;
    int count = 0;
    while (count < hexCodeSequence.Length) {
        string hexCode = hexCodeSequence.Substring(count, 2);
        bytes[index] = getHexValue(hexCode);
        count += 2;
        index += 1;
    }

    return bytes;
}

public static byte getHexValue(string hexCode)
{
    return byte.Parse(hexCode, System.Globalization.NumberStyles.HexNumber);
}
}
数据是55字节长,但我必须把它放在56字节。它向数组的and追加一个0字节,但如果我不这样做,cryptostream会抛出一个错误,即要解密的数据太短

如果我这样做,我只会得到垃圾作为输出。我使用的是空的salt和IV,因为我看不出java代码使用的是哪个salt和IV。是否有我不知道的默认值

编辑: 从hexCode中提取字节的Java代码:

private static byte getNegativeValueForHexConversion(String hexCode) {
int i = Integer.parseInt(hexCode, 16);
return (byte) (i > 127 ? i - 256 : i);
}

看起来Java使用有符号字节,.Net对其所有函数使用无符号字节。这可能是问题所在吗?

DES是一种块大小为64位的分组密码。因此(至少在ECB模式下)必须解密的密文长度必须是64位(8字节)的倍数。你的是55字节,所以你没有完整的密文-这就是为什么你必须添加一个零字节。您是否自己运行了Java代码,并看到输出长度为55字节?这是复制粘贴错误吗

除此之外,DES的使用模式可以有效地创建密钥流,然后与明文异或生成密文。这将包括CFB、OFB和CTR模式。因此,有一种可能性是,使用其中一种方法进行解密是可行的(我不知道.NET加密库是否支持CTR)。您确定在Java代码中指定了ECB吗


但是,您也有一个问题,Java代码看起来像是在从键文本进行简单的文本到十六进制的转换,以获得键字节,而.NET代码正在进行RFC-2898兼容的转换,这将不会为您提供相同的键字节。

确保没有复制和粘贴错误。我将尝试运行Java代码。ECB是在说明如何解密数据的规范中指定的。我在上面的post.OK中附加了将十六进制字符串转换为字节数组的函数。这绝对不是使用DES的ECB加密的输出,因此不能使用ECB进行解密。让我知道当您运行Java代码进行加密时会发生什么…我尝试运行Java代码,但失败了。所以我再次查看输入字符串,发现我得到了错误的加密数据。原始加密数据的长度为64字节,可以正常工作。谢谢你的帖子真的帮助了我!
private static byte getNegativeValueForHexConversion(String hexCode) {
int i = Integer.parseInt(hexCode, 16);
return (byte) (i > 127 ? i - 256 : i);
}