最近在做一个小小的对称加解密工具,需要跨Java和.NET。
本来想着这东西都有规范的,按理说不应该跟语言有关:大家都简单用下SDK的api,然后他们自己会懂的。
可是还是有点小小的意外,记上一笔,以作后续参考。
1. 我本来打算用DES,简单就好了,别太复杂,后来发现两者鸡跟鸭讲(why?),互相一直认识不了,就简单改成了3DES(无非是getInstance的时候改几个字符而已了)。
2. Key一定要24个字符,然后getBytes。
3. IV用8个byte就好了,为了用IV,CBC就不错
4. Padding我以为一定要弄NoPadding,其实我发现用java默认的PKCS5Padding就很好NoPadding(post comment: 如果用PKCS5Padding而不是NoPadding,会导致.NET加密的在java上无法解密,但奇怪的是java到.net方向却没有问题。再次why?),而.net用Zeros。
下面是关键代码,附上:
1. Java
初始化部分:
//KEY=UE9XRVIgQlkgQlJJR0hUIFpI byte[] key = Constants.SECURITY__KEY.getBytes("UTF-8"); //iv=byte[8]{...} IvParameterSpec ips = new IvParameterSpec(iv); SecretKeySpec keySpec = new SecretKeySpec(key, "DESede"); //encodeClipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); encodeClipher = Cipher.getInstance("DESede/CBC/NoPadding"); encodeClipher.init(Cipher.ENCRYPT_MODE, keySpec, ips); //decodeClipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); encodeClipher = Cipher.getInstance("DESede/CBC/NoPadding"); decodeClipher.init(Cipher.DECRYPT_MODE, keySpec, ips);
加密部分:
//date=byte[] byte[] encryptedData= encodeClipher.doFinal(data);
解密部分:
//data=byte[] byte[] decryptedData= decodeClipher.doFinal(data);
2. .NET
加密部分:
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider(); des.Key = inputKey; des.IV = ivArray; des.Mode = CipherMode.CBC; des.Padding = PaddingMode.Zeros; ICryptoTransform transform = des.CreateEncryptor(des.Key, des.IV); MemoryStream mem = new MemoryStream(); CryptoStream encStream = new CryptoStream(mem, transform, CryptoStreamMode.Write); encStream.Write(plainData, 0, plainData.Length); byte[] ciphertext = mem.ToArray(); encStream.Dispose(); mem.Dispose();
解密部分:
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider(); des.Key = inputKey; des.IV = ivArray; des.Mode = CipherMode.CBC; des.Padding = PaddingMode.Zeros; ICryptoTransform transform = des.CreateDecryptor(des.Key, des.IV); MemoryStream memDecryptStream = new MemoryStream(); CryptoStream cs_decrypt = new CryptoStream(memDecryptStream, transform, CryptoStreamMode.Write); cs_decrypt.Write(ciphertext, 0, ciphertext.Length); byte[] plaintext = memDecryptStream.ToArray(); cs_decrypt.Close(); memDecryptStream.Dispose();
可参考:
http://docs.oracle.com/javase/1.4.2/docs/guide/security/jce/JCERefGuide.html
http://docstore.mik.ua/orelly/java-ent/security/ch13_05.htm
http://www.jensign.com/JavaScience/dotnet/NetDESEncrypt/