Java TripleDESCryptoServiceProvider等效于Java

拜托,请不要问我为什么。 我只是在.NET中使用此代码来加密/解密数据字符串。 我现在需要在java中制作“完全”相同的function。 我已经为DESede crypt尝试了几个例子,但它们都没有给出与.net中这个类相同的结果。

我甚至在ssl后面制作一个.net webserbvice来服务于.net写的这两种方法但是如果不用尽所有的可能性就太愚蠢了。

也许你们中的一些在这个领域更有相关性的java人将会在你们的头脑中如何制作它。

谢谢 !!!

public class Encryption { private static byte[] sharedkey = {...}; private static byte[] sharedvector = {...}; public static String Decrypt(String val) { TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); byte[] toDecrypt = Convert.FromBase64String(val); MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, tdes.CreateDecryptor( sharedkey, sharedvector ), CryptoStreamMode.Write); cs.Write(toDecrypt, 0, toDecrypt.Length); cs.FlushFinalBlock(); return Encoding.UTF8.GetString(ms.ToArray()); } public static String Encrypt(String val) { TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); byte[] toEncrypt = Encoding.UTF8.GetBytes(val); MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, tdes.CreateEncryptor( sharedkey, sharedvector ), CryptoStreamMode.Write); cs.Write(toEncrypt, 0, toEncrypt.Length); cs.FlushFinalBlock(); return Convert.ToBase64String(ms.ToArray()); } } 

Samle输入/输出

 String plain = "userNameHere:passwordHere"; Console.WriteLine("plain: " + plain); String encrypted = Encrypt(plain); Console.WriteLine("encrypted: " + encrypted); // "zQPZgQHpjxR+41Bc6+2Bvqo7+pQAxBBVN+0V1tRXcOc=" String decripted = Decrypt(encrypted); Console.WriteLine("decripted: " + decripted); // "userNameHere:passwordHere" 

代码如下,但首先是几个注释。

  1. 必须为每个消息选择不同的初始化向量。 硬编码初始化向量没有意义。 IV应与密文一起发送给消息接收者(这不是秘密)。
  2. 我使用自己的实用程序类进行base-64编码。 您可以使用sun.misc.BASE64Encodersun.misc.BASE64Decoder ,使用像BouncyCastle这样的第三方库,或者编写自己的库。
  3. 您正在使用双键三重DES,其中第一个键和第三个键相同。 我修改了sharedkey以反映这一点,因为Java DESede密码总是需要192位密钥; 由键生成器来处理键控选项。
  4. CBC IV仅为64位。 我只使用了sharedvector的前64位。

该类应与C#版本互操作。

 import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class Encryption { private static byte[] sharedkey = { 0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11, 0x12, 0x11, 0x0D, 0x0B, 0x07, 0x02, 0x04, 0x08, 0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11 }; private static byte[] sharedvector = { 0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11 }; public static void main(String... argv) throws Exception { String plaintext = "userNameHere:passwordHere"; String ciphertext = encrypt(plaintext); System.out.println(ciphertext); System.out.println(decrypt(ciphertext)); } public static String encrypt(String plaintext) throws Exception { Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding"); c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sharedkey, "DESede"), new IvParameterSpec(sharedvector)); byte[] encrypted = c.doFinal(plaintext.getBytes("UTF-8")); return Base64.encode(encrypted); } public static String decrypt(String ciphertext) throws Exception { Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding"); c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sharedkey, "DESede"), new IvParameterSpec(sharedvector)); byte[] decrypted = c.doFinal(Base64.decode(ciphertext)); return new String(decrypted, "UTF-8"); } } 

输出:

zQPZgQHpjxR + 41Bc6 + 2Bvqo7 + pQAxBBVN + 0V1tRXcOc =

userNameHere:passwordHere

你有一些问题,

  1. 如果要在.NET和Java上生成相同的密钥材料,则密钥必须为24个字节。
  2. IV必须是块大小,对于Triple DES是8字节。
  3. 在Java中,您需要指定默认模式和填充,即“DESede / CBC / NoPadding”。

一旦进行了这些更改,您应该能够在Java端解密它。

您是否确定.NET代码使用与Java代码相同的填充? 我看到.NET代码中没有指定填充,这就是我问的原因。

您是否碰巧拥有Java代码的源代码,它将帮助您找到错误。

请尝试以下方法。 对于实际使用,我会得到一个像commons编解码器一样的base64库,或者使用BouncyCastle附带的编解码器

 import java.io.IOException; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; public class Encryption { private static SecretKey sharedkey; private static byte [] sharedvector; static { int keySize = 168; int ivSize = 8; try { KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede"); keyGenerator.init(keySize); sharedkey = keyGenerator.generateKey(); sharedvector = new byte [ivSize]; byte [] data = sharedkey.getEncoded(); int half = ivSize / 2; System.arraycopy(data, data.length-half, sharedvector, 0, half); System.arraycopy(sharedvector, 0, sharedvector, half, half); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } public static void main(String [] args) throws Exception { System.out.println(Decrypt(Encrypt("Hello World"))); } public static String Encrypt(String val) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, sharedkey, new IvParameterSpec(sharedvector)); return new sun.misc.BASE64Encoder().encode(cipher.doFinal(val.getBytes())); } public static String Decrypt(String val) throws GeneralSecurityException, IOException { Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, sharedkey, new IvParameterSpec(sharedvector)); return new String(cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(val))); } }