java .net 3des_Java.net3DES差异及互通
主要差異如下:
1、? 對于待加密解密的數據,各自的填充模式不一樣
C#的模式有:ANSIX923、ISO10126、None、PKCS7、Zero,而Java有:NoPadding、PKCS5Padding、SSL3Padding
2、? 各自默認的3DES實現,模式和填充方式不一樣
C#的默認模式為CBC,默認填充方式為PKCS7; java的默認模式為ECB,默認填充方式為PKCS5Padding
3、? 各自的key的size不一樣
C#中key的size為16和24均可;java中要求key的size必須為24;對于CBC模式下的向量iv的size兩者均要求必須為8
翻看了3DES的原理:
DES主要采用替換和移位的方法,用56位密鑰對64位二進制數據塊進行加密,每次加密可對64位的輸入數據進行16輪編碼,
經一系列替換和移位后,輸入的64位轉換成安全不同的64的輸出數據
.
3DES:是在DES的基礎上采用三重DES,即用兩個56位的密鑰K1,K2,發送方用K1加密,K2解密,再使用K1加密.接收方使用K1解密,K2加密,再使用K1解密,
其效果相當于密鑰長度加倍.
于是嘗試在java中,對key進行補位,即用前8個字節作為byte[24] 中的byte[16]~byte[23];發現與c#中加密的結果相同!于是大膽假設C#中可能是檢查key的size為16的時候
自動將前8個字節作為k3進行了補位,而java沒有實現這一點(因為java的3DES算法中強制要求key的size必須為24)。這樣的情況下,可能就是發送方用k1加密、k2解密、k3再加密;接受方k3解密、k2加密、再k1解密來實現。
最終經過編碼驗證,確認key大小為24時,java和c#的加密解密結果相一致。
Java中實現時,只要注意對大小不足24的key進行補位,和采用CBC模式,填充模式為PKCS5Padding即可。
C#中的實現:
public void test()
{
SymmetricAlgorithm des = new TripleDESCryptoServiceProvider();
des.Key = Encoding.UTF8.GetBytes("wserrtyuiop12fer");
des.IV = Encoding.UTF8.GetBytes("12345678");
string str = "test";
byte[] byt = Encoding.UTF8.GetBytes(str);
MemoryStream ms = new MemoryStream();
ICryptoTransform ct = mCSP.CreateEncryptor(des.Key, des.IV);
CryptoStream? cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
cs.Write(byt, 0, byt.Length);
cs.FlushFinalBlock();
cs.Close();
string enctext64=Convert.ToBase64String(ms.ToArray());
Console.Out.WriteLine("enctext64: {0}", enctext64);
}
Java中的實現:
public static void main(String[] args) {
try {
byte[] key = "wserrtyuiop12fercsffswqh".getBytes();
byte[] iv = "12345678".getBytes();
String s = "test";
s="9EC610E687CA2642147F3BB1779E1C56:820124";
BASE64Decoder base64decoder = new BASE64Decoder();
BASE64Encoder base64encoder = new BASE64Encoder();
iv = base64decoder.decodeBuffer("H06BDKgg/kI=");
byte[] bt = base64decoder.decodeBuffer("nsYQ5ofKJkIUfzuxd54cVg==");
System.out.println("original key size:" + bt.length);
byte[] kbt = new byte[bt.length + 8];
System.arraycopy(bt, 0, kbt, 0, bt.length);
System.arraycopy(bt, 0, kbt, 16, 8);
System.out.println("key base64: " + base64encoder.encode(kbt));
key=kbt;
System.out.println("key size:" + key.length);
String result = encryptWithIV(key, iv, s);
System.out.println("encrypt result: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String encryptWithIV(byte[] key, byte[] iv, String str) throws Exception {
SecureRandom sr = new SecureRandom();
DESedeKeySpec dks = new DESedeKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
IvParameterSpec ips = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, securekey, ips, sr);
byte[] bt = cipher.doFinal(str.getBytes("utf-8"));
System.out.println("encrypt base64: " + new BASE64Encoder().encode(bt));
return new String(Hex.encodeHex(bt));
}
還有一種讓Java和.Net兼容的方式,在.Net中指定模式為ECB,填充為PKCS7,然后在Java中采用其默認的模式(DESede/ECB/PKCS5Padding)即可,注意雙方約定key的size為24個字節。建議雙方對key以base64編碼字符串進行告知,因為java和.net中byte字節的范圍不相同(前者-128~127,后者0~255),避免不必要的處理。
總結
以上是生活随笔為你收集整理的java .net 3des_Java.net3DES差异及互通的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sqlplus中调用shell_记一次突
- 下一篇: 合同相似可逆等价矩阵的关系及性质_行列式