c# - Java 中的 .NET TripleDESCryptoServiceProvider 等价物

标签 c# java .net encryption 3des

请不要问我为什么。我在 .NET 中只有这段代码可以加密/解密数据字符串。我现在需要在 Java 中实现“完全”相同的功能。我已经为 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());
  }
}

示例输入/输出

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. 必须为每条消息选择不同的初始化 vector 。硬编码初始化 vector 没有意义。 IV 应与密文一起发送给消息收件人(这不是 secret )。
  2. 我使用自己的实用程序类进行 base-64 编码。您可以改用 sun.misc.BASE64Encodersun.misc.BASE64Decoder,使用第三方库(如 BouncyCaSTLe),或编写您自己的库。
  3. 您使用的是双 key 三重 DES,其中第一个 key 和第三个 key 相同。我修改了 sharedkey 以反射(reflect)这一点,因为 Java DESede 密码总是需要 192 位 key ;由 key 生成器来处理键控选项。
  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

关于c# - Java 中的 .NET TripleDESCryptoServiceProvider 等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1400830/

相关文章:

c# - WPF MVVM,我应该把 View 的特定属性放在哪里?

c# - 如何测试包含 Application.Current.Properties.ContainsKey ("token"的方法

c# - ASP.NET MVC3 向下钻取复选框列表

c# - 在 .NET 中自行安装 Windows 服务

java - 如何在一个点中存储 double ?

c# - 从System.Web.HttpInputStream获取文件信息

c# - RestSharp 中的参数计数不匹配错误?

java - 使用类实例的计算器错误

java - 使用 Guice 注入(inject)时如何在 Java 中正确处理长期存在的 MySQL 连接?

c# - 在 Sqlite3 中存储 System.Uri