为了账号安全,请及时绑定邮箱和手机立即绑定

TripleDES加密在java中工作正常,但在c中不起作用#

TripleDES加密在java中工作正常,但在c中不起作用#

C#
蝴蝶不菲 2022-08-20 15:12:46
我在进行三重DES加密时面临弱密钥错误。代码在java中工作正常,但在C# .net中给出错误。我有Java代码,其中TripleDES ecryption工作正常,我需要在c#中转换我的Java代码。我在转换过程中面临弱键错误。下面给出了java和c#代码。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;    }}密钥:02020202020202020202020202020202数据 : 041205FFFBA666CF结果 : A334C92CEC163D9F任何人都可以用c#编写代码,产生与java相同的结果。
查看完整描述

2 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

在我开始之前,我想说的是,我不建议或认可您遵循这种方式来强制TripleDES使用它认为较弱的密钥,但是,鉴于您仅将其用于解密,这里有一种使用反射的方法。


首先,您必须“强制”类获取要使用的弱键。为此,我们使用反射来绕过对弱键的检查,当您尝试设置键 () 并直接设置成员变量时,将执行该检查:TripeDESalg.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);

现在的键值将设置为弱键 (TripleDESalg.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


查看完整回答
反对 回复 2022-08-20
?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

3DES 键是一个 24 字节值,它分为两个三个 8 字节值:、 、 .key0key1key2


因为 3DES 是 DES_Encrypt(key2, DES_Decrypt(key1, DES_Encrypt(key0, data))) 任何时间都等于或算法简化为 DES。这就是.NET的TripleDES正在警告你。key1key2key0


这里正确的测试应该考虑清除(或设置或修复)每个字节中的奇偶校验位,但手挥的版本是:


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;


查看完整回答
反对 回复 2022-08-20
  • 2 回答
  • 0 关注
  • 121 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信