【问题标题】:Different result of after converting 3DES program from C# to Java将 3DES 程序从 C# 转换为 Java 后的不同结果
【发布时间】:2019-03-06 04:44:09
【问题描述】:

我有一个 c# 程序如下:

public static string Encrypt(string sClear, string sKey)
        {
            sClear = "4140700104596085";
            sKey = "222222222222222222222222222222222222222222222222";

            TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
            cryptoProvider.Mode = CipherMode.ECB;

            byte[] bData = new byte[16];
            byte[] bKey = new byte[24];

            // Convert from hex to decimal
            FromHexToDecimal(sClear).CopyTo(bData, 0);
            FromHexToDecimal(sKey).CopyTo(bKey, 0);

            ICryptoTransform cTransform = DESCryptoExtensions.CreateWeakEncryptor(cryptoProvider, bKey, cryptoProvider.IV);
            byte[] result = cTransform.TransformFinalBlock(bData, 0, bData.Length);

            return BitConverter.ToString(result).Replace("-", "").Substring(0, 16);
        }

我的明文是“4140700104596085”,我的密钥是“22222222222222222222222222222222222”,这个程序将返回“0C90320B7B9EC798”作为结果。

现在我正在尝试用 java 代码来做,这是我的代码:

public static String encryptToString(String message) throws Exception {
      message = "4140700104596085";
      final MessageDigest md = MessageDigest.getInstance("md5");
      final byte[] digestOfPassword = md.digest("222222222222222222222222222222222222222222222222"
              .getBytes("utf-8"));
      final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
      for (int j = 0, k = 16; j < 8;) {
          keyBytes[k++] = keyBytes[j++];
      }

      final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
      final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
      final Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
      cipher.init(Cipher.ENCRYPT_MODE, key);
      // cipher.init(Cipher.ENCRYPT_MODE, key, iv);

      final byte[] plainTextBytes = message.getBytes("utf-8");
      final byte[] cipherText = cipher.doFinal(plainTextBytes);

      return Hex.encodeHexString(cipherText).substring(0, 16);
  }

如你所见,我评论了cipher.init(Cipher.ENCRYPT_MODE, key, iv);,因为我会遇到java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV 错误。

即使我评论它,我得到的结果仍然不同,它是f8f8739fb41259d6。我认为我的 Java 代码有问题,有什么想法吗?

我在谷歌上试过,但翻译起来并不那么直接。

【问题讨论】:

  • 请注意,您正在对 java 版本中的密钥进行 MD5 哈希处理,然后对其执行另一个小例程。在 C# 中,您根本不会这样做。
  • 即使我将它替换为final byte[] digestOfPassword = "222222222222222222222222222222222222222222222222".getBytes("utf-8");,它仍然没有得到相同的结果。我怀疑我的 java 代码有问题,这与 c# 所做的不一样。
  • 请注意,如果您替换 digestOfPassword,您仍在运行修改 keyBytes 的 for 循环,而您在 C# 中没有这样做。
  • 我太笨了。看到你的评论后,我设法得到它。我应该关闭这个问题吗?还是直接离开?
  • 您可以修复您的代码并将其添加为答案 :) 尽管可能不会做完全相同的事情,但将来有人可能会发现拥有等效的 C# 和 Java 代码的一些价值。

标签: java c# encryption translate 3des


【解决方案1】:

我找到了解决办法。

我应该遵循 C# 中的代码。

因此,我删除了

final MessageDigest md = MessageDigest.getInstance("md5");
      final byte[] digestOfPassword = md.digest("222222222222222222222222222222222222222222222222"
              .getBytes("utf-8"));
      final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
      for (int j = 0, k = 16; j < 8;) {
          keyBytes[k++] = keyBytes[j++];
      }

并替换为

final byte[] keyBytes = fromHexToDecimal("222222222222222222222222222222222222222222222222");

fromHexToDecimal 方法如下:

public static byte[] fromHexToDecimal(String hex) {

      int len = hex.length() / 2;
      byte[] result = new byte[len];

      for (int i = 0, j = 0; i < len; i++, j = j + 2) {
        StringBuilder c = new StringBuilder();
        c = c.append(hex.charAt(j)).append(hex.charAt(j+1));
        short s = (short) Integer.parseInt(c.toString(), 16);
        result[i] = (byte)(s & 0xff);
      }


      return result;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 2019-02-22
    • 1970-01-01
    • 2013-01-21
    • 2019-04-09
    相关资源
    最近更新 更多