【问题标题】:C# and Java DES Encryption value are not identicalC# 和 Java DES 加密值不相同
【发布时间】:2012-10-15 11:30:29
【问题描述】:

我正在尝试使用 C# 和 Java 加密相同的数据。如果数据超过 7 个字节,则 Java 和 C# 的加密值不相同。

  • 输入 1:a
    java 输出:FrOzOp/2Io8=
    C# 输出:FrOzOp/2Io8=

  • 输入 2:abc
    j : H9A/ahl8K7I=
    c#: H9A/ahl8K7I=

  • 输入 3:aaaaaaaa问题
    j : Gxl7e0aWPd7j6l7uIEuMxA==
    c#:Gxl7e0aWPd7sf1xR6hK4VQ==

这里是 C# 和 Java 方法的实现。
C#代码:

public String saltTxt = "12345678";
public String Encrypt(String txt)
{
        byte[] data = Encrypt(Encoding.UTF8.GetBytes(txt));
        
        DESCryptoServiceProvider alg = new DESCryptoServiceProvider();

        alg.Key = Encoding.UTF8.GetBytes(saltTxt.ToCharArray(), 0, cprovider.KeySize / 8);
        alg.IV = new byte[8];

        MemoryStream ms = new MemoryStream();
        CryptoStream stem = new CryptoStream( ms, cprovider.CreateEncryptor(),CryptoStreamMode.Write);

        stem.Write(txt, 0, txt.Length);
        stem.FlushFinalBlock();

        data = ms.ToArray();
        
        return Convert.ToBase64String(data);
 }

Java 代码:

public String saltTxt = "12345678";
public String Encrypt(String str) {
    try {
        KeySpec myKey = new DESKeySpec(saltTxt.getBytes("UTF8"));
        SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(myKey);
        Cipher ecipher = Cipher.getInstance("DES");
        ecipher.init(Cipher.ENCRYPT_MODE, key);

        byte[] data = str.getBytes("UTF8");

        byte[] crypt = ecipher.doFinal(data);
        
        return new BASE64Encoder().encode(crypt);
    } catch (Exception ex) {
    }

    return null;
} 

知道为什么它没有按预期工作吗?

【问题讨论】:

  • 听起来像是填充问题。见msdn.microsoft.com/en-us/library/…
  • 重要的是两者之间的往返应该有效。是吗?
  • @JonSkeet 是的,这是填充问题。 java的默认填充机制是什么?如果我在 java 部分中指定DES/CBC/PKCS5Padding,那么这两个值将变得相同。
  • @NiksonKantiPaul:那么这不能解决你的问题吗?
  • 是的,问题解决了。谢谢

标签: c# java encryption cryptography


【解决方案1】:

问题出在mode 的加密中。

SunJCE 提供程序使用 ECB 作为默认模式,并使用 PKCS5Padding 作为 DES、DES-EDE 和 Blowfish 密码的默认填充方案。 (JCA Doc)

.Net中,对称算法的默认操作模式是CipherMode.CBC,默认填充是PaddingMode.PKCS7。 (msdn..SymmetricAlgorithm)

以下更改解决了该问题。

// in C# 
DESCryptoServiceProvider alg = new DESCryptoServiceProvider();
alg.Mode = CipherMode.ECB;  // specified 

// in java
chiper = Cipher.getInstance("DES/CBC/PKCS5Padding");

两边都不要变。

【讨论】:

    【解决方案2】:

    您可能会看到 ISO 10126 填充,它将随机字节附加到纯文本中以将其填充到块大小的倍数。
    此行为是设计使然。

    【讨论】:

    • @NiksonKantiPaul:Java 中没有。
    【解决方案3】:

    下面的代码(Java/Android)对我有用。 我在 C# 上使用了相同的方法。

    public static String Cripto(String Password)
    {
        String PasswordCripto = "";
        try
        {
            String encryptionKey = "anyEncryptionString";
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(encryptionKey.getBytes("UTF-8"), 0, encryptionKey.length());
            byte[] encryptionKeyBytes = messageDigest.digest();
    
            SecretKeySpec Key = new SecretKeySpec(encryptionKeyBytes,"DESede");
            Cipher cipher = Cipher.getInstance("DESEDE/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, Key);
            byte[] encryptedBytes = cipher.doFinal(Password.getBytes("UTF-8"));
    
            PasswordCripto = new String(Base64.encode(encryptedBytes, Base64.DEFAULT), "UTF-8");
        } catch(Exception e) { }
        return PasswordCripto ;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 2017-08-25
      • 2016-12-10
      • 2015-01-03
      • 2015-09-03
      相关资源
      最近更新 更多