AES Encryption in Java and Decryption in C#

后端 未结 4 783
终归单人心
终归单人心 2020-11-30 06:19

Hello I\'ve Encrypted Hex string and Key that has been encrypted using standard AES Algorithm. Code:

        final String key = \"=abcd!#Axd*G!pxP\";
                


        
相关标签:
4条回答
  • 2020-11-30 06:42

    Try this combination:

    aesAlg.Mode = CipherMode.ECB;   
    aesAlg.Padding = PaddingMode.PKCS7;   
    //aesAlg.IV; - use default (not assign)   
    
    0 讨论(0)
  • 2020-11-30 06:54

    Your code has one big problem: It is mixing the character encodings!

    In Java you are calling key.getBytes(), without arguments. This method returns the UTF-8 or CP1252/ISO 8859-1 encoded data depending on your operating system and the default charset in Java.

    On C# side you are using Encoding.Unicode.GetBytes(key) - "Unicode" in .Net is a synonym for double byte characters alias UTF-16 (Little-Endian). Therefore you are using a different key in C#.

    You should be able to see the difference by comparing the number of bytes in Java and C#:

    Java: "=abcd!#Axd*G!pxP".getBytes().length = 16

    C#: Encoding.Unicode.GetBytes("=abcd!#Axd*G!pxP").Length = 32

    I strongly recommend you to use byte arrays instead of Strings for defining a cryptographic key.

    Update: Another difference is that you are setting an initialization vector (IV) in C# which you don't do in Java. As you are using ECB the IV should not be used but if you change to CBC for example this makes a big difference.

    0 讨论(0)
  • 2020-11-30 07:02

    I suspect the error is that you aren't specifying a padding or mode of operation in the Java side of this equation. I'm not sure what Java's AES implementation defaults to, but I would start by specifying both when you obtain the cipher. For instance:

    Cipher.getInstance("<algorithm>/<mode of operation>/<padding>");
    

    You'll need to look up the supported padding schemes and modes of operation for AES in Java and then make sure you configure your C# code to use the exact same configuration.

    0 讨论(0)
  • 2020-11-30 07:07

    I needed something not only for C# but also Silverlight and Windows Phone 7 compatible. And I'm definitely sick of the lack full examples of something acceptable both in Java and C# (and Base64 based).

    Code isn't anything fancy, but works. Please feel free to improve upon it, as I marked this as community wiki, but make sure to test it before submitting any changes to it.

    Here's the C# code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security.Cryptography;
    using System.IO;
    //Author: Doguhan Uluca
    //Website: www.deceivingarts.com
    
    namespace DeceivingArts.Common
    {
        public class Encryptor
        {
            private string _seed = "";
    
            public Encryptor(string seed)
            {
            _seed = seed;
            }
    
            public string Encrypt<TSymmetricAlgorithm>(string input) where TSymmetricAlgorithm : SymmetricAlgorithm, new()
            {
                var pwdBytes = Encoding.UTF8.GetBytes(_seed);
                using(TSymmetricAlgorithm sa = new TSymmetricAlgorithm())
                {
                    ICryptoTransform saEnc = sa.CreateEncryptor(pwdBytes, pwdBytes);
    
                    var encBytes = Encoding.UTF8.GetBytes(input);
    
                    var resultBytes = saEnc.TransformFinalBlock(encBytes, 0, encBytes.Length);
    
                    return Convert.ToBase64String(resultBytes);
                }
            }
    
            public string Decrypt<TSymmetricAlgorithm>(string input) where TSymmetricAlgorithm : SymmetricAlgorithm, new()
            {
                var pwdBytes = Encoding.UTF8.GetBytes(_seed);
                using(TSymmetricAlgorithm sa = new TSymmetricAlgorithm())
                {
                    ICryptoTransform saDec = sa.CreateDecryptor(pwdBytes, pwdBytes);
    
                    var encBytes = Convert.FromBase64String(input);
    
                    var resultBytes = saDec.TransformFinalBlock(encBytes, 0, encBytes.Length);
                    return Encoding.UTF8.GetString(resultBytes);
                }
            }
        }
    }
    

    Here's the Android compatible Java code:

    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    /**
     * Usage:
     * <pre>
     * String crypto = SimpleCrypto.encrypt(masterpassword, cleartext)
     * ...
     * String cleartext = SimpleCrypto.decrypt(masterpassword, crypto)
     * </pre>
     * @author ferenc.hechler
     * @author Doguhan Uluca
     */
    public class Encryptor {
    
        public static String encrypt(String seed, String cleartext) throws Exception {
                byte[] rawKey = getRawKey(seed.getBytes());
                byte[] result = encrypt(rawKey, cleartext.getBytes());
                return toBase64(result);
        }
    
        public static String decrypt(String seed, String encrypted) throws Exception {
                byte[] rawKey = getRawKey(seed.getBytes());
                byte[] enc = fromBase64(encrypted);
                byte[] result = decrypt(rawKey, enc);
                return new String(result);
        }
    
        private static byte[] getRawKey(byte[] seed) throws Exception {
            SecretKey skey = new SecretKeySpec(seed, "AES");
    
            byte[] raw = skey.getEncoded();
    
            return raw;
        }
    
        private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(raw);
    
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
            byte[] encrypted = cipher.doFinal(clear);
            return encrypted;
        }
    
        private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(raw);
    
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
            byte[] decrypted = cipher.doFinal(encrypted);
            return decrypted;
        }
    
        public static String toBase64(byte[] buf)
        {
            return Base64.encodeBytes(buf);
        }
    
        public static byte[] fromBase64(String str) throws Exception
        {
            return Base64.decode(str);
        }
    }
    

    For the Base64 conversion please see the excellent implementation at http://iharder.net/base64.

    I hope this saves people hours.

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