Encrypt in java and Decrypt in C# For AES 256 bit

1.I have java function which encrypt xml file and return encrypted String.

/// Java Class 
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class Crypt {

    public static String key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    public static byte[] key_Array = Base64.decodeBase64(key);

    public static String encrypt(String strToEncrypt)
    {       
        try
        {   
            //Cipher _Cipher = Cipher.getInstance("AES");
            //Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            //Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");      

            Key SecretKey = new SecretKeySpec(key_Array, "AES");

            Cipher _Cipher = Cipher.getInstance("AES");     
            _Cipher.init(Cipher.ENCRYPT_MODE, SecretKey);       

            return Base64.encodeBase64String(_Cipher.doFinal(strToEncrypt.getBytes()));     
        }
        catch (Exception e)
        {
            System.out.println("[Exception]:"+e.getMessage());
        }
        return null;
    }

    public static void main(String[] args) {        
        StringBuilder sb = new StringBuilder();
        sb.append("xml file string ...");

        String EncryptedString = encrypt(sb.toString());        
        System.out.println("[EncryptedString]:"+EncryptedString);
    }
}

2.I have c# function which decrypt the message which is encrypted by java function.

/// C# Function
private static string Decrypt(string encryptedText)
{
    RijndaelManaged aesEncryption = new RijndaelManaged();            
    aesEncryption.BlockSize = 256;
    //aesEncryption.KeySize = 256;
    //aesEncryption.Mode = CipherMode.CBC;
    //aesEncryption.Padding = PaddingMode.PKCS7;

    string keyStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    //string ivStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";        

    byte[] keyArr = Convert.FromBase64String(keyStr);
    //byte[] ivArr = Convert.FromBase64String(ivStr);

    aesEncryption.Key = keyArr;
    //aesEncryption.IV = ivArr;

    ICryptoTransform decrypto = aesEncryption.CreateDecryptor();

    byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length);  
    byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); /// CryptographicException: Length of the data to decrypt is invalid.    
    return ASCIIEncoding.UTF8.GetString(decryptedData); 
}

Java encrypt function is work well. But the problem is C# function,
when I decrypt I get below error message

CryptographicException: Length of the data to decrypt is invalid.

I searched solutions by using below ref

  • AES Encryption in Java and Decryption in C#
  • C# / Java | AES256 encrypt/decrypt
  • Encyption/Decryption in C# and Java
  • but I still face the same error.Could anyone give me suggestion please.

    Updated

    I Just change my C# crypto function. Below is my change lists

  • Block Size to 128
  • Key Size to 256
  • IV Size to 16
  • Key Size to 32
  • /// Updated decrypt function
    private static string Decrypt(string encryptedText)
    {
        RijndaelManaged aesEncryption = new RijndaelManaged();            
        aesEncryption.BlockSize = 128;
        aesEncryption.KeySize = 256;
    
        //aesEncryption.Mode = CipherMode.CBC;
        aesEncryption.Padding = PaddingMode.None;
    
        string keyStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        string ivStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";           
    
        byte[] ivArr = Convert.FromBase64String(ivStr);
        byte[] IVkey16BytesValue = new byte[16];
        Array.Copy(ivArr, IVkey16BytesValue, 16);
    
        byte[] keyArr = Convert.FromBase64String(keyStr);
        byte[] KeyArr32BytesValue = new byte[32];
        Array.Copy(keyArr, KeyArr32BytesValue, 32);
    
        aesEncryption.IV = IVkey16BytesValue;
        aesEncryption.Key = KeyArr32BytesValue; 
    
        ICryptoTransform decrypto = aesEncryption.CreateDecryptor();
    
        byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length);
        byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); 
        return ASCIIEncoding.UTF8.GetString(decryptedData);
    }
    

    In this time, no error occur. But I get decrypted message which i cannot read.

    g:��td��Y符O����rL��W�wHm�>f�au����%��0�� ..........
    

    Please let me get your suggestion again.


    I believe the blockSize should be 128 and the keysize be 256. The keyStr should be 32 characters long and the IVstr should be 16 characters long. This may help as it describes why 128 bits have to be used for block size and what the key sizes can be. csrc.nist.gov/publications/fips/fips197/fips-197.pdf

    You have this in the decrypt method.

        aesEncryption.Padding = PaddingMode.None; 
    

    I believe you need to put that in the encrypt method also.

    Also why not use this method for the key and IV.

        aes.Key = ASCIIEncoding.ASCII.GetBytes(keyStr); 
        aes.IV = ASCIIEncoding.ASCII.GetBytes(ivStr);
    

    After I got very helpful suggestions from @deathismyfriend and other, I found out what I am missing in my C# Decrypt function.So I change my function as below.

    /// C# Error Fixed Version - CipherMode.ECB
    public static string keyStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    
    private static string Encrypt(string PlainText)
    {
        RijndaelManaged aes = new RijndaelManaged();
        aes.BlockSize = 128;
        aes.KeySize = 256;
    
        /// In Java, Same with below code
        /// Cipher _Cipher = Cipher.getInstance("AES");  // Java Code
        aes.Mode = CipherMode.ECB; 
    
        byte[] keyArr = Convert.FromBase64String(keyStr);
        byte[] KeyArrBytes32Value = new byte[32];
        Array.Copy(keyArr, KeyArrBytes32Value, 32);
    
        aes.Key = KeyArrBytes32Value;
    
        ICryptoTransform encrypto = aes.CreateEncryptor();
    
        byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(PlainText);
        byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);
        return Convert.ToBase64String(CipherText);
    }
    
    private static string Decrypt(string CipherText)
    {  
        RijndaelManaged aes = new RijndaelManaged();
        aes.BlockSize = 128;
        aes.KeySize = 256;
    
        /// In Java, Same with below code
        /// Cipher _Cipher = Cipher.getInstance("AES");  // Java Code
        aes.Mode = CipherMode.ECB;
    
        byte[] keyArr = Convert.FromBase64String(keyStr);
        byte[] KeyArrBytes32Value = new byte[32];
        Array.Copy(keyArr, KeyArrBytes32Value, 32);
    
        aes.Key = KeyArrBytes32Value;
    
        ICryptoTransform decrypto = aes.CreateDecryptor();
    
        byte[] encryptedBytes = Convert.FromBase64CharArray(CipherText.ToCharArray(), 0, CipherText.Length);
        byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
        return ASCIIEncoding.UTF8.GetString(decryptedData);
    }
    

    By using upper c# function , now I can decrypt and read cipher text.
    Below is what I found out after I getting error again and again.

    CryptographicException: Padding is invalid and cannot be removed.
    
     Solution:  
    _RijndaelManaged.Padding = CipherMode.xxx;    ///should toggle here
    _RijndaelManaged.Padding = PaddingMode.xxx;   ///should toggle here 
    
    
    CryptographicException: Length of the data to decrypt is invalid. 
    CryptographicException: Specified initialization vector (IV) does not match the block size for this algorithm.
    
    Solution
    1. _RijndaelManaged.BlockSize = 128; /// Must be
    2. _RijndaelManaged.KeySize = 256; /// Must be
    3. _RijndaelManaged.Key = Byte Array Size must be 32 in length ( more detail 32*8 = 256 KeySize )
    4. _RijndaelManaged.IV = Byte Array Size must be 16 in length ( more detail 16*8 = 128 BlockSize)
    

    But when it come to security reason, I think I should not use ECB mode.
    According to

  • ECB mode is not secure
  • StackOverFlow link
  • So I Modify it again in Java and C#.

    // Java code - Cipher mode CBC version.
    // CBC version need Initialization vector IV.
    // Reference from https://stackoverflow.com/questions/6669181/why-does-my-aes-encryption-throws-an-invalidkeyexception/6669812#6669812
    
    import java.security.Key;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import org.apache.commons.codec.binary.Base64;
    
    public class CryptoSecurity {
    
        public static String key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        public static byte[] key_Array = Base64.decodeBase64(key);
    
        public static String encrypt(String strToEncrypt)
        {       
            try
            {   
                //Cipher _Cipher = Cipher.getInstance("AES");
                //Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
                Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");        
    
                // Initialization vector.   
                // It could be any value or generated using a random number generator.
                byte[] iv = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
                IvParameterSpec ivspec = new IvParameterSpec(iv);
    
                Key SecretKey = new SecretKeySpec(key_Array, "AES");    
                _Cipher.init(Cipher.ENCRYPT_MODE, SecretKey, ivspec);       
    
                return Base64.encodeBase64String(_Cipher.doFinal(strToEncrypt.getBytes()));     
            }
            catch (Exception e)
            {
                System.out.println("[Exception]:"+e.getMessage());
            }
            return null;
        }
    
        public static String decrypt(String EncryptedMessage)
        {
            try
            {
                //Cipher _Cipher = Cipher.getInstance("AES");
                //Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
                Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");            
    
                // Initialization vector.   
                // It could be any value or generated using a random number generator.
                byte[] iv = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
                IvParameterSpec ivspec = new IvParameterSpec(iv);
    
                Key SecretKey = new SecretKeySpec(key_Array, "AES");
                _Cipher.init(Cipher.DECRYPT_MODE, SecretKey, ivspec);           
    
                byte DecodedMessage[] = Base64.decodeBase64(EncryptedMessage);
                return new String(_Cipher.doFinal(DecodedMessage));
    
            }
            catch (Exception e)
            {
                System.out.println("[Exception]:"+e.getMessage());          
    
            }
            return null;
        }
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            StringBuilder sb = new StringBuilder();
    
            sb.append("xml file string ...");
    
            String outputOfEncrypt = encrypt(sb.toString());        
            System.out.println("[CryptoSecurity.outputOfEncrypt]:"+outputOfEncrypt);
    
            String outputOfDecrypt = decrypt(outputOfEncrypt);        
            //String outputOfDecrypt = decrypt(sb.toString());        
            System.out.println("[CryptoSecurity.outputOfDecrypt]:"+outputOfDecrypt);
        }
    
    }
    

    In C#, I modify it like below.

    // C# Code, CipherMode.CBC
    // CBC version need Initialization vector IV.
    
    public static string keyStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    private static string Encrypt(string PlainText)
    {
        RijndaelManaged aes = new RijndaelManaged();
        aes.BlockSize = 128;
        aes.KeySize = 256;
    
        // It is equal in java 
        /// Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");    
        aes.Mode = CipherMode.CBC;  
        aes.Padding = PaddingMode.PKCS7; 
    
        byte[] keyArr = Convert.FromBase64String(keyStr);
        byte[] KeyArrBytes32Value = new byte[32];
        Array.Copy(keyArr, KeyArrBytes32Value, 32);
    
        // Initialization vector.   
        // It could be any value or generated using a random number generator.
        byte[] ivArr = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
        byte[] IVBytes16Value = new byte[16];
        Array.Copy(ivArr, IVBytes16Value, 16);
    
        aes.Key = KeyArrBytes32Value;
        aes.IV = IVBytes16Value;
    
        ICryptoTransform encrypto = aes.CreateEncryptor();
    
        byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(PlainText);
        byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);
        return Convert.ToBase64String(CipherText);
    
    }
    
    private static string Decrypt(string CipherText)
    {
        RijndaelManaged aes = new RijndaelManaged();
        aes.BlockSize = 128;
        aes.KeySize = 256;
    
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
    
        byte[] keyArr = Convert.FromBase64String(keyStr);
        byte[] KeyArrBytes32Value = new byte[32];
        Array.Copy(keyArr, KeyArrBytes32Value, 32);
    
        // Initialization vector.   
        // It could be any value or generated using a random number generator.
        byte[] ivArr = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };            
        byte[] IVBytes16Value = new byte[16];
        Array.Copy(ivArr, IVBytes16Value, 16);
    
        aes.Key = KeyArrBytes32Value;
        aes.IV = IVBytes16Value;
    
        ICryptoTransform decrypto = aes.CreateDecryptor();
    
        byte[] encryptedBytes = Convert.FromBase64CharArray(CipherText.ToCharArray(), 0, CipherText.Length);
        byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
        return ASCIIEncoding.UTF8.GetString(decryptedData);
    }
    

    Now it all work.
    For more detail about AES, click this link which I was given by @deathismyfriend.
    It is also very useful.


    On one of my recent projects I was tasked with building up a url with an encrypted portion to pass to another website. They ran java on their server, whereas we developed in c#.

    I know this isn't an exact match to what you were tasked to create, but hopefully this can help out others that are trying to find answers :)

    I received the following from their developers to build our encryption off from

    在这里输入图像描述

    To accomplish this in c# I did the following:

        public String Encrypt(String plainText, String key)
        {
            var plainBytes = Encoding.UTF8.GetBytes(plainText);
            return Convert.ToBase64String(Encrypt(plainBytes, GetRijndaelManaged(key)));
        }
    
        private RijndaelManaged GetRijndaelManaged(String secretKey)
        {
            var keyBytes = new byte[16];
            var secretKeyBytes = Encoding.ASCII.GetBytes(secretKey);
            Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
            return new RijndaelManaged
            {
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7,
                KeySize = 128,
                BlockSize = 128,
                Key = keyBytes,
                IV = keyBytes
    
            };
        }
    
        private byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
        {
            return rijndaelManaged.CreateEncryptor()
                .TransformFinalBlock(plainBytes, 0, plainBytes.Length);
        }
    
    链接地址: http://www.djcxy.com/p/49162.html

    上一篇: 如何模拟Javascript crypto AES

    下一篇: 在Java中加密并在C#中解密用于AES 256位