我在执行三重DES加密时遇到密钥错误。代码在Java中工作正常,但在C#.net中给出了错误。
我有可以在TripleDES加密中正常工作的Java代码,我需要在c#中转换我的java代码。我在转换过程中面临弱密钥错误。在给出的java和c#代码下面。
1)Java代码
post_install do |installer|
installer.pods_project.targets.each do |target|
setup_all_swift_versions(target, my_project_pods_swift_versions)
end
end
2)C#代码
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);
}
}
键:020202020202020202020202020202020202
数据:041205FFFBA666CF
结果:A334C92CEC163D9F
任何人都可以用c#编写产生与Java相同结果的代码。
答案 0 :(得分:0)
在我开始之前,我想说我不推荐或支持您遵循这种方式,以迫使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
最后,在创建解密器时将进一步检查弱密钥,因此我们必须再次使用Reflection绕过该检查并创建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
来使用任何键。
答案 1 :(得分:0)
3DES密钥是一个24字节的值,该值分为两个三个8字节的值:key0
,key1
,key2
。
由于任何时候key1
等于key2
或key0
时,3DES都是DES_Encrypt(key2,DES_Decrypt(key1,DES_Encrypt(key0,data)))),因此算法被简化为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;