C# to Java TripleDES , different results

后端 未结 1 1852
你的背包
你的背包 2021-02-06 17:41

I\'m attempting to convert this C# encryption algorithm to Java; however, I keep retrieving slightly different encrypted results (haven\'t tried decryption yet). It may also be

相关标签:
1条回答
  • 2021-02-06 18:20

    You are missing two things. You are using a 16 length key on the c# side since it is not padded like the Java version. By default if the key is 16 bytes in length it will be padded with the first 8 bytes of the key.

    To make this match on the Java side you will have to uncomment that line that adds the padding to the key:

    for (int j = 0, k = 16; j < 8;) {
      keyBytes[k++] = keyBytes[j++];
    }
    
    SecretKey secretKey = new SecretKeySpec(keyBytes, 0, 24, "DESede");
    

    Also, on the java side there was a suggestion to make sure to use UTF-LE for the text. Make sure to use it for everything. So the lines:

    byte[] digestOfPassword = md.digest(key.getBytes("UTF-16LE"));
    
    byte[] plainTextBytes = clearText.getBytes("UTF-16LE");
    

    In general I would make sure to set the c# params of all the tripledes object, and not depend on defaults.

    Here are two versions that match in c# and java

    Java

    String key = "012345678901234567890123";
    String clearText = "test";
    
    MessageDigest md = MessageDigest.getInstance("md5");
    byte[] digestOfPassword = md.digest(key.getBytes("UTF-16LE"));
    
    byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
    String byteText = Arrays.toString(keyBytes);
    
    for (int j = 0, k = 16; j < 8;) {
      keyBytes[k++] = keyBytes[j++];
    }
    
    SecretKey secretKey = new SecretKeySpec(keyBytes, 0, 24, "DESede");
    
    IvParameterSpec iv = new IvParameterSpec(new byte[8]);
    Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
    
    byte[] plainTextBytes = clearText.getBytes("UTF-16LE");
    byte[] cipherText = cipher.doFinal(plainTextBytes);
    
    String output = Base64.encode(cipherText);
    

    c#

    string clearText = "test";
    string key = "012345678901234567890123";
    string encryptedText = "";
    
    MD5 md5 = new MD5CryptoServiceProvider();
    TripleDES des = new TripleDESCryptoServiceProvider();
    des.KeySize = 128;
    des.Mode = CipherMode.CBC;
    des.Padding = PaddingMode.PKCS7;
    
    byte[] md5Bytes = md5.ComputeHash(Encoding.Unicode.GetBytes(key));
    
    byte[] ivBytes = new byte[8];
    
    
    des.Key = md5Bytes;
    
    des.IV = ivBytes;
    
    byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
    
    ICryptoTransform ct = des.CreateEncryptor();
    using (MemoryStream ms = new MemoryStream())
    {
        using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
        {
            cs.Write(clearBytes, 0, clearBytes.Length);
            cs.Close();
        }
        encryptedText = Convert.ToBase64String(ms.ToArray());
    }
    

    Edited: Both versions now return the test case result "nmj8MjjO52y928Syqf0J+g=="

    0 讨论(0)
提交回复
热议问题