Comprimento da Chave Inválida Java do AES Encryption

Eu estou tentando criar um método de criptografia AES, mas por algum motivo eu continuo recebendo

java.security.InvalidKeyException: Key length not 128/192/256 bits

Aqui está o código:

 public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); // NOTE: last argument is the key length, and it is 256 KeySpec spec = new PBEKeySpec(password, salt, 1024, 256); SecretKey tmp = factory.generateSecret(spec); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); return(secret); } public static byte[] encrypt(char[] password, byte[] salt, String text) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{ SecretKey secret = getSecretKey(password, salt); Cipher cipher = Cipher.getInstance("AES"); // NOTE: This is where the Exception is being thrown cipher.init(Cipher.ENCRYPT_MODE, secret); byte[] ciphertext = cipher.doFinal(text.getBytes("UTF-8")); return(ciphertext); } 

Alguém pode ver o que estou fazendo errado? Eu estou pensando que pode ter algo a ver com o algoritmo SecretKeyFactory, mas isso é o único que posso encontrar que é suportado no sistema final que estou desenvolvendo contra. Qualquer ajuda seria apreciada. Obrigado.

Para obter uma criptografia de força de chave mais forte, é necessário fazer o download dos Arquivos de Política de Jurisdição de Força Ilimitada do Java Cryptography Extension (JCE).

http://java.sun.com/javase/downloads/index.jsp (verifique outros downloads).

Você pode instalar os flasks JCE Unlimited Strength, como é sugerido em várias outras perguntas similares, ou apenas tentar include este código em sua function principal ou driver.

 try { java.lang.reflect.Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted"); field.setAccessible(true); field.set(null, java.lang.Boolean.FALSE); } catch (Exception ex) { ex.printStackTrace(); } 

O problema aqui é a incompatibilidade entre tamanhos de chave para a function de derivação de chave e as cifras dadas. O PBKDF que você usa é "PBEWithMD5AndDES" e nesta string a parte DES indica o tipo de saída. Como DES único, como é conhecido, utiliza apenas chaves de 8 bytes (64 bit, 56 bit de tamanho efetivo com bits de paridade). As chaves AES devem ser 128, 192 e 256 bits e não devem include bits de paridade.

Para criar tamanhos de chave de força AES, você deve usar pelo menos PBKDF2 em vez de PBKDF1, de preferência com SHA-256 ou SHA-512 para tamanhos de chave maiores. Para chaves de 128 bits, você deve estar bem com o SHA-1. Portanto, use a compilation em "PBKDF2WithHmacSHA1" SecretKeyFactory . Observe que PBKDF2 / SHA1 com chaves acima de 160 bits resultará em operação abaixo do ideal. Você pode querer usar uma function de derivação de chave baseada em chave simples (KBKDF) sobre a saída se quiser criar mais dados (como um IV separado).

Como outros indicaram, se você usar chaves de mais de 128 bits, precisará dos arquivos de jurisdição de criptografia ilimitados.


Notas sobre o seguinte código:

  • Nenhuma proteção de integridade, que você pode precisar mesmo para manter a confidencialidade
  • CBC usando um IV zero, isso pode ser OK, mas apenas se o sal for totalmente random (armazene o sal com o texto cifrado)
  • 1024 é um número relativamente baixo de iterações para o PBKDF2
  • PBKDF2 é incompatível com PBKDF1 que você estava usando
 public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); // NOTE: last argument is the key length, and it is 128 KeySpec spec = new PBEKeySpec(password, salt, 1024, 128); SecretKey tmp = factory.generateSecret(spec); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); return(secret); } public static byte[] encrypt(char[] password, byte[] salt, String text) throws GeneralSecurityException { SecretKey secret = getSecretKey(password, salt); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(new byte[cipher.getBlockSize()])); byte[] ciphertext = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8)); return(ciphertext); } 

usando quaisquer mecanismos de preenchimento para preencher os bits vazios

 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

Quando eu coloco o seguinte código e o executo, não recebo nenhuma exceção:

 import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; public class Main { public static void main(String[] args) { String pass = "this is the pass"; char[] pw = new char[pass.length()]; for(int k=0; k 

Eu nunca consegui recriar a exceção que você tinha. Estou executando o J2SE 1.6 e desenvolvendo no Eclipse.

Pode ser que sua senha não tenha 16 bytes?