2010-04-02 2 views
9

Я пытаюсь создать метод шифрования AES, но по какой-то причине я получаюшифрования AES Java Invalid Длина ключа

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

Вот код:

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); 
} 

Может ли кто-нибудь увидеть, что я делаю неправильно? Я думаю, что это может иметь какое-то отношение к алгоритму SecretKeyFactory, но это единственный, который я могу найти, который поддерживается в конечной системе, с которой я развиваюсь. Любая помощь будет оценена по достоинству. Благодарю.

+1

Можете ли вы вставить исключение? –

+0

Существует ответ в более раннем посте в [этой ссылке] (http://stackoverflow.com/questions/992019/java-256bit-aes-encryption/992413#992413). Надеюсь это поможет! –

+0

так, кажется, что экземпляр java не поддерживает то, что мне нужно: «Ява.security.InvalidKeyException с сообщением« Недопустимый размер ключа или параметры по умолчанию »' – wuntee

ответ

-1

с использованием любых механизмов отступы, чтобы заполнить пустые биты

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

oops, извините это дополнение для ввода не для ключа –

8

Для более сильного ключа шифрования силы вам нужно будет загрузить Java Cryptography Extension (JCE) Безлимитный Strength политики Юрисдикция файлов.

http://java.sun.com/javase/downloads/index.jsp (Проверить другие загрузки).

+0

Я загрузил дополнительные банки, добавил их в проект, но все равно получаю исключение ... – wuntee

+0

Вы не добавляете их в проект, это библиотеки времени выполнения , В файле README.txt указано, что вы должны установить их в свою папку безопасности во время выполнения (перезапишите там файлы) Если вы используете JDK, то:/path/to/jdk/jre/libs/security/ Если вместо этого вы используете JRE :/path/to/jre/libs/security/ –

+0

Решили ли вы решить вопрос? –

-1

Когда я устанавливаю следующий код и запустить его, я не получаю никаких исключений:

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<pass.length();++k) 
     { 
      pw[k] = pass.charAt(k); 
     } 
     try { 
      byte[] q = encrypt(pw,"asdf".getBytes(),"der text"); 
      System.out.println(new String(q)); 
     } catch (InvalidKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchAlgorithmException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidKeySpecException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidParameterSpecException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalBlockSizeException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (UnsupportedEncodingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

    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); 
    } 
} 

Я никогда не был в состоянии воссоздать исключение, которое вы имели. Я запускаю J2SE 1.6 и развиваюсь на Eclipse.

Может быть, ваш пароль не длиной 16 байт?

+0

Пароль не является ключом. Пользователь правильно использовал функцию определения ключа на основе пароля (PBKDF). Вы удалили эту требуемую защиту. Подсказка: есть такая вещь, как 'GeneralSecurityException', и обычно вы либо бросаете ее в свой метод, либо создаете исключение из среды выполнения (например,' IllegalStateException', если алгоритм не может быть найден). –

+0

Я не удалял никакой защиты. Метод encrypt() вызывает getSecretKey(), который вызывает PBEKeySpec() так же, как OP имеет в своем исходном коде. – Chopstick

2

Вы можете установить банки JCE Unlimited Strength, как предлагается по нескольким другим подобным вопросам, или просто попробуйте включить этот код в свою основную функцию или драйвер.

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(); 
} 
+0

не работает в java 8 –

2

Проблема заключается в несоответствии между размерами ключей для вашей функции деривации ключей и данных шифров. Используемый PBKDF - "PBEWithMD5AndDES", и в этой строке часть DES указывает тип выхода. Как один DES, поскольку он известен, использует только 8-байтовые ключи (64 бит, 56 эффективных бит-бит с битами четности). Клавиши AES должны быть 128, 192 и 256 бит и не должны содержать биты четности.

Чтобы создать максимальные размеры ключей AES, вы должны, по крайней мере, использовать PBKDF2 вместо PBKDF1, предпочтительно с SHA-256 или SHA-512 для более высоких размеров ключа. Для 128-битных ключей вы должны быть в порядке с SHA-1. Поэтому используйте построение в "PBKDF2WithHmacSHA1"SecretKeyFactory. Обратите внимание, что PBKDF2/SHA1 с ключами более 160 бит приведет к субоптимальной операции. Вы можете использовать функцию вывода ключа на основе ключевых ключей (KBKDF) на выходе, если вы хотите создать больше данных (например, отдельный IV).

Как указывали другие, если вы используете ключи размером более 128 бит, вам понадобятся неограниченные файлы подписи криптозащиты.


Замечания по следующему коду:

  • Нет защиты целостности, которая вам может понадобиться даже для сохранения конфиденциальности
  • CBC с использованием нулевой IV, это может быть в порядке, но только тогда, когда соль полностью беспорядочно (хранить соль с зашифрованным текстом)
  • 1024 - относительно небольшое количество итераций для PBKDF2
  • PBKDF2 несовместим с PBKDF1, который вы использовали
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); 
}