How to fix Invalid AES key length?

后端 未结 4 725
我在风中等你
我在风中等你 2020-12-12 22:39

I am working on a text encryption and decryption project (following Struts 2)

Whenever I enter the password and the plain text I get a Invalid AES K

相关标签:
4条回答
  • 2020-12-12 22:47

    I was facing the same issue then i made my key 16 byte and it's working properly now. Create your key exactly 16 byte. It will surely work.

    0 讨论(0)
  • 2020-12-12 22:50

    Things to know in general:

    1. Key != Password
      • SecretKeySpec expects a key, not a password. See below
    2. It might be due to a policy restriction that prevents using 32 byte keys. See other answer on that

    In your case

    The problem is number 1: you are passing the password instead of the key.

    AES only supports key sizes of 16, 24 or 32 bytes. You either need to provide exactly that amount or you derive the key from what you type in.

    There are different ways to derive the key from a passphrase. Java provides a PBKDF2 implementation for such a purpose.

    I used erickson's answer to paint a complete picture (only encryption, since the decryption is similar, but includes splitting the ciphertext):

    SecureRandom random = new SecureRandom();
    byte[] salt = new byte[16];
    random.nextBytes(salt);
    
    KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 256); // AES-256
    SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    byte[] key = f.generateSecret(spec).getEncoded();
    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
    
    byte[] ivBytes = new byte[16];
    random.nextBytes(ivBytes);
    IvParameterSpec iv = new IvParameterSpec(ivBytes);
    
    Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
    c.init(Cipher.ENCRYPT_MODE, keySpec, iv);
    byte[] encValue = c.doFinal(valueToEnc.getBytes());
    
    byte[] finalCiphertext = new byte[encValue.length+2*16];
    System.arraycopy(ivBytes, 0, finalCiphertext, 0, 16);
    System.arraycopy(salt, 0, finalCiphertext, 16, 16);
    System.arraycopy(encValue, 0, finalCiphertext, 32, encValue.length);
    
    return finalCiphertext;
    

    Other things to keep in mind:

    • Always use a fully qualified Cipher name. AES is not appropriate in such a case, because different JVMs/JCE providers may use different defaults for mode of operation and padding. Use AES/CBC/PKCS5Padding. Don't use ECB mode, because it is not semantically secure.
    • If you don't use ECB mode then you need to send the IV along with the ciphertext. This is usually done by prefixing the IV to the ciphertext byte array. The IV is automatically created for you and you can get it through cipherInstance.getIV().
    • Whenever you send something, you need to be sure that it wasn't altered along the way. It is hard to implement a encryption with MAC correctly. I recommend you to use an authenticated mode like CCM or GCM.
    0 讨论(0)
  • 2020-12-12 22:58

    You can verify the key length limit:

    int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
    System.out.println("MaxAllowedKeyLength=[" + maxKeyLen + "].");
    
    0 讨论(0)
  • 2020-12-12 23:04

    You can use this code, this code is for AES-256-CBC or you can use it for other AES encryption. Key length error mainly comes in 256-bit encryption.

    This error comes due to the encoding or charset name we pass in the SecretKeySpec. Suppose, in my case, I have a key length of 44, but I am not able to encrypt my text using this long key; Java throws me an error of invalid key length. Therefore I pass my key as a BASE64 in the function, and it converts my 44 length key in the 32 bytes, which is must for the 256-bit encryption.

    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.MessageDigest;
    import java.security.Security;
    import java.util.Base64;
    
    public class Encrypt {
    
        static byte [] arr = {1,2,3,4,5,6,7,8,9};
    
        // static byte [] arr = new byte[16];
    
          public static void main(String...args) {
            try {
             //   System.out.println(Cipher.getMaxAllowedKeyLength("AES"));
                Base64.Decoder decoder = Base64.getDecoder();
                // static byte [] arr = new byte[16];
                Security.setProperty("crypto.policy", "unlimited");
                String key = "Your key";
           //     System.out.println("-------" + key);
    
                String value = "Hey, i am adnan";
                String IV = "0123456789abcdef";
           //     System.out.println(value);
                // log.info(value);
              IvParameterSpec iv = new IvParameterSpec(IV.getBytes());
                //    IvParameterSpec iv = new IvParameterSpec(arr);
    
            //    System.out.println(key);
                SecretKeySpec skeySpec = new SecretKeySpec(decoder.decode(key), "AES");
             //   System.out.println(skeySpec);
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //    System.out.println("ffffdffffdffffd"+IV);
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
           //     System.out.println(cipher.getIV());
    
                byte[] encrypted = cipher.doFinal(value.getBytes());
                String encryptedString = Base64.getEncoder().encodeToString(encrypted);
    
                System.out.println("encrypted string,,,,,,,,,,,,,,,,,,,: " + encryptedString);
                // vars.put("input-1",encryptedString);
                //  log.info("beanshell");
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题