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

前端 未结 4 1059
无人及你
无人及你 2020-12-03 01:44

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         


        
4条回答
  •  抹茶落季
    2020-12-03 02:30

    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

    1. ECB mode is not secure
    2. 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.

提交回复
热议问题