TripleDes的加密工作在Java罚款,但不是在C#

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TripleDes的加密工作在Java罚款,但不是在C#相关的知识,希望对你有一定的参考价值。

我面临的弱密钥错误,而这样做的TripleDES encryption.Code工作在Java罚款,但在C#.NET给错误。

我在这三重DES加密工作正常,我需要转换我的Java代码在C#。我现在面临弱密钥错误conversion.Below期间Java和C#代码给出的Java代码。

1)Java代码的

public class TripleDES {
    private DESedeKeySpec desKeySpec;

    public TripleDES(String key) {
        try {
            byte[] keyBytes = { (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x02,
                    (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x02,
                    (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x02,
                    (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x02,
                    (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x02,
                    (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x02};



            this.desKeySpec = new DESedeKeySpec(keyBytes);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public byte[] encrypt(byte[] origData) {
        try {
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
            SecretKey key = factory.generateSecret(this.desKeySpec);
            Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return cipher.doFinal(origData);
        }  catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public byte[] decrypt(byte[] crypted) {
        try {
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
            SecretKey key = factory.generateSecret(this.desKeySpec);
            Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");  //DESede/CBC/PKCS5Padding
            cipher.init(Cipher.DECRYPT_MODE, key);
            return cipher.doFinal(crypted);
        }  catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) throws Exception {
        TripleDES des = new TripleDES("");

      byte[] data = { (byte)0x04, (byte)0x12, (byte)0x05, (byte)0xFF, (byte)0xFB, (byte)0xA6, (byte)0x66, (byte)0xCF};
      //byte[] data = { (byte)0x04, (byte)0x12, (byte)0x15, (byte)0xAF, (byte)0xFD, (byte)0xD8, (byte)0x88, (byte)0xBB};  


//-----------------Edited-----------------
String text = new BigInteger(1, data).toString(16);
System.out.println("Before encryption = " +text);             
    byte[] crypted = des.encrypt(data);
String text1 = new BigInteger(1, crypted).toString(16);
    System.out.println("Encrypted = " +text1);
byte[] decrypted = des.decrypt(crypted);
String text2 = new BigInteger(1, decrypted).toString(16);
    System.out.println("Decrypted = " +text2);
    }

}

2)C#代码

    static void Main(string[] args)
    {
        String Data = EncryptDES("041205FFFBA666CF");
    }

    public static string EncryptDES(string InputText)
    {
        byte[] key = new byte[] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 };
        byte[] clearData = System.Text.Encoding.UTF8.GetBytes(InputText);
        MemoryStream ms = new MemoryStream();
        TripleDES alg = TripleDES.Create();
        alg.Key = key;
        alg.Mode = CipherMode.ECB;
        CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
        cs.Write(clearData, 0, clearData.Length);
        cs.FlushFinalBlock();
        byte[] CipherBytes = ms.ToArray();
        ms.Close();
        cs.Close();
        string EncryptedData = Convert.ToBase64String(CipherBytes);
        return EncryptedData;

    }

重点:02020202020202020202020202020202

数据:041205FFFBA666CF

结果:A334C92CEC163D9F

任何人都可以请编写C#代码产生的结果相同的Java。

答案

在我开始,我想说的是,我不推荐或认可您按照这种方式迫使TripleDes的使用它认为关键是弱,不过,由于您使用它进行解密只是,这里是一个办法做到它使用反射。

首先,您必须“强制”的TripeDES类带您要使用的弱密钥。要做到这一点,我们使用反射来绕过那就是当你尝试设置键(alg.Key = key)进行弱密钥检查,并直接设置成员变量:

//alg.Key = key; - THIS IS REPLACED BY THE BELOW
FieldInfo keyField = alg.GetType().GetField("KeyValue", BindingFlags.NonPublic | BindingFlags.Instance);
keyField.SetValue(alg, key);

TripleDES的键值,将被设置到你的弱密钥(alg.Key);

接下来你有一个小的失误,因为你忘记关闭填充:

alg.Mode = CipherMode.ECB;
alg.Padding = PaddingMode.None; // Add this, as the default padding is PKCS7

最后,将是创建解密时弱密钥进一步检查,所以我们必须再次使用反射来绕过检查和创建ICryptoTransform的:

// Comment out the below line and use the code below
// CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
ICryptoTransform Decryptor;
MethodInfo createMethod = alg.GetType().GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
Decryptor = createMethod.Invoke(alg, new object[] { alg.Key, alg.Mode, alg.IV, alg.FeedbackSize, 1 }) as ICryptoTransform;
CryptoStream cs = new CryptoStream(ms, Decryptor, CryptoStreamMode.Write);

现在,该代码将运行并接受弱密钥,并执行你正在寻找解密。

但是,它不看,我认为输出是你期待什么:

?Data
"4aU3DcHkiCTEywpiewWIow=="

至少现在虽然你可以使用你想要TripleDES哪个键。

另一答案

甲3DES密钥是24字节的值,该值被分解两个三8字节值:key0key1key2

因为3DES是DES_ENCRYPT(KEY2,DES算法(KEY1,DES_ENCRYPT(KEY0,数据)))的任何时间key1等于key2key0算法减小到DES。这是.NET的TripleDes的警告你一下。

这里的合适的测试应占在每个字节清零(或设置,或固定)的奇偶校验比特,但手波形版本是:

SymmetricAlgorithm alg;
IEnumerable<byte> key0 = key.Take(8);
IEnumerable<byte> key1 = key.Skip(8).Take(8);
IEnumerable<byte> key2 = key.Skip(16);

if (key0.SequenceEquals(key1))
{
    alg = DES.Create();
    alg.Key = key2.ToArray();
}
else if (key1.SequenceEquals(key2))
{
    alg = DES.Create();
    alg.Key = key0.ToArray();
}
else
{
    alg = TripleDES.Create();
    alg.Key = key;
}

要更换你的两个内胆:

TripleDES alg = TripleDES.Create();
alg.Key = key;

以上是关于TripleDes的加密工作在Java罚款,但不是在C#的主要内容,如果未能解决你的问题,请参考以下文章

多语言(Java&C#&Ruby&C++&Objective-C&Android)互通的TripleDES加解密算法实现

TripleDES 加密在 c# 和 PHP 中没有得到相同的结果

加密算法:AES DES RC4 Rabbit TripleDes 那个更好??它们分

php和java中的加密和解密

常见对称加密

js 加密解密 TripleDES