Search code examples
javac#encryptionaes

Padding is invalid and cannot be removed - decryption in c# (encryption done in java)


Java code

public String encrypt(String key, String value) {
    try {
      String initVector = "RgUkXp2s5v8y/B?E";
      IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
      SecretKeySpec skeySpec = new SecretKeySpec(hashKey(key), "AES");
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
      cipher.init(1, skeySpec, iv);
      byte[] encrypted = cipher.doFinal(value.getBytes());
      return Base64.getEncoder().encodeToString(encrypted);
    } catch (Exception ex) {
      ex.printStackTrace();
      return null;
    } 
  }
  
  private byte[] hashKey(String keyValue) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    byte[] key = keyValue.getBytes("UTF-8");
    MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
    key = messageDigest.digest(key);
    return Arrays.copyOf(key, 16);
  }



public static String decrypt(byte[] key, String encrypted)
{
    try
    {
        String initVector = "RgUkXp2s5v8y/B?E";
        IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(2, skeySpec, iv);
        byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));
        return new String(original);
    }
    catch (Exception ex)
    {
        Logger.getLogger("Decryption ").log(Level.SEVERE, "Exception processing decryption " + ex.getMessage());
        return null;
    }
}

String encryptedLicense = ENCRYPT.encrypt(string_key, stringToEncrypt);




converted c# code

   public static byte[] getDefaultKey()
{
    return DecryptUtil.hashKey(DecryptUtil.getUniqueIdentifier());
}


private static byte[] hashKey(string keyValue)
{
    try
    {
        var sha1 = SHA1Managed.Create();
        byte[] inputBytes = Encoding.UTF8.GetBytes(keyValue);
        byte[] outputBytes = sha1.ComputeHash(inputBytes);
        return outputBytes;
       
    }
    catch (Exception ex)
    {
        ErrorLogger.WriteToFile("hashKey " + ex.Message.ToString());
    }
    return null;
}

public static string Decrypt_License(string encryptedText, byte[] key)
{
    string initVector = "RgUkXp2s5v8y/B?E";
                var ivBytes = Encoding.UTF8.GetBytes(initVector);
                var keyBytes = new byte[16];
                Array.Copy(key, keyBytes, Math.Min(keyBytes.Length, key.Length));
                string plaintext = null;
                // Create AesManaged    
                using (AesManaged aes = new AesManaged())
                {
                    aes.Padding = PaddingMode.PKCS7;
                    aes.Key = keyBytes;
                    aes.IV = ivBytes;
                    aes.BlockSize = 128;
                    aes.KeySize = 128;
                    aes.Mode = CipherMode.CBC;
                     
                    ICryptoTransform decryptor = aes.CreateDecryptor(keyBytes, ivBytes);
                   
                    
                    using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(encryptedText)))
                    {
                       
                        using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                        {
                               
                            using (StreamReader reader = new StreamReader(cs))
                                plaintext = reader.ReadToEnd();
                        }
                    }
                }
                return plaintext;
}

String decryptedString = DecryptUtil.Decrypt_License(hashkey(string_key), stringToDecrypt);

I am converting java code to c#, encryption done in java now I am trying to decrypt the data in c# . I read PaddingMode.PKCS7 and PKCS5 both are same. Is it true? or should I change padding type?

I have used all the concepts which is used in java. but it is not working. Am I missing something?

I have doubt in Convert.FromBase64String(encryptedText), because this is the place they(java) have used value.getBytes(). getBytes() equivalent in c# is Convert.FromBase64String()? will they produce same result?

Java hashkey() method and C# hashkey method giving different results. How to compare them as byte[]?

If I change Convert.FromBase64String() to Encoding.UTF8.GetBytes() then it is throwing 'Length of the data to decrypt is invalid AES C#' error.

This is my encrypted text wJZESOEPNb66FbnpB8DqmwLcyosxGOjzgPKa9+7/VUatEFxSs1YqS28HHU26EmCcZDo7otE5PvX/qIpgQgTrhlCHgUJBb0+qd522/1egYoisE48ZL8X3cwCNx1AOVYJ0T2VOLB+J3HDWK4HOJfgm2CqbQpep0ioOTgNKQA0SF3SRmF92MGbf7wjUBA8WGdeUiIKRX9Lm/x6mUUuXHEIrCHbZOqDZvo2xR9zndIzwT/FfgLsQbJQjRjZPg7urfWLpUt6drbYcPFm3KgTmSrsRhzk15P6mw3GNO+3BmqBIndKmzi8blQqG8YFXVW8wiaurCm0jVcX5kwdU1PO1ktHSXQ==

secret key used for encryption BFEBFBFF000306D4


Solution

  • I used my own decryption method for c# aes and hashKey as well as I know they are working :-).

    Giving these data as input for the Java encryption:

    String string_key = "mySecretKey";
    String stringToEncrypt = "The quick brown fox jumps over the lazy dog";
    

    I'm getting the

    encryptedLicense: lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK
    

    Using this string and the given string_key to C# is puts out:

    plaintext expect : The quick brown fox jumps over the lazy dog
    plaintext from C#: The quick brown fox jumps over the lazy dog
    

    Security warning: this code uses a fixed encryption key and a fixed initialization vector that makes the complete encryption UNSECURE. The code has not proper exception handling and is for educational purpose only.

    C#-code:

    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Text;
    
    public class Program {
        public static void Main() {
            Console.WriteLine("Padding is invalid and cannot be removed - decryption in c# (encryption done in java)");
    
            string plaintextExpected = "The quick brown fox jumps over the lazy dog";
            string encryptedLicense = "lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK";
            string string_key = "mySecretKey";
            string plaintext = "";
    
            // decryption
            plaintext = decryptFromBase64(hashKey(string_key), encryptedLicense);
            Console.WriteLine("plaintext expect : " + plaintextExpected);
            Console.WriteLine("plaintext from C#: " + plaintext);
        }
    
        public static byte[] hashKey(string value)
        {
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(value);
            SHA1 sha = new SHA1CryptoServiceProvider();
            byte[] sha1Hash = sha.ComputeHash(bytes);
            byte[] sha1HashLength = new byte[16];
            Array.Copy(sha1Hash, 0, sha1HashLength, 0, 16);
            return sha1HashLength;
        }
    
        static string decryptFromBase64(byte[] key, string data) {
            string decryptedtext;
            using(Aes aesAlg = Aes.Create()) {
                aesAlg.Key = key;
                string initVector = "RgUkXp2s5v8y/B?E";
                byte[] IV = Encoding.UTF8.GetBytes(initVector);
                byte[] cipherText = Convert.FromBase64String(data);
                aesAlg.IV = IV;
                aesAlg.Mode = CipherMode.CBC;
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                using(var msDecrypt = new MemoryStream(cipherText)) {
                    using(var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
                        using(var srDecrypt = new StreamReader(csDecrypt)) {
                            decryptedtext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            return decryptedtext;
        }
    }
    

    Edit 1: In my Java code I changed the following line:

    //String string_key = "mySecretKey";
    String string_key = "BFEBFBFF000306D4";
    

    and got as result:

    encryptedLicense: 7QWzpg/rVE6AhmcGphFT9uswU8hgKjG3i9NHJHCn/fKITYNIljOb28+cbh5y5JEA
    

    Changing my C#-code as follow:

    //string encryptedLicense = "lrgzfdMTetZKeAFlCAbCDBL4VhtpVGdhTESl9QNgs5b0KOWke1CnKQQf+xmB+/mK";
    string encryptedLicense = "7QWzpg/rVE6AhmcGphFT9uswU8hgKjG3i9NHJHCn/fKITYNIljOb28+cbh5y5JEA";
    //string string_key = "mySecretKey";
    string string_key = "BFEBFBFF000306D4";
    

    gets the result:

    plaintext expect : The quick brown fox jumps over the lazy dog
    plaintext from C#: The quick brown fox jumps over the lazy dog
    

    So everything is working.