2012-05-31 2 views
11

При запуске ниже программы я получаю это исключение. Не удалось выяснить, что проблема, поскольку AES позволяет использовать бит 128 -256 бит?Получение исключения java.security.InvalidKeyException: Неверная длина ключа AES: 29 байтов?

Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 29 bytes 
at com.sun.crypto.provider.AESCipher.engineGetKeySize(DashoA13*..) 
at javax.crypto.Cipher.b(DashoA13*..) 

Получение исключение в строке 20

Вот программа

import java.security.Key; 

import javax.crypto.Cipher; 
import javax.crypto.spec.SecretKeySpec; 

import sun.misc.BASE64Decoder; 
import sun.misc.BASE64Encoder; 

public class AESEncryptionDecryptionTest { 

    private static final String ALGORITHM  = "AES"; 
    private static final String myEncryptionKey = "ThisIsSecurityKey"; 
    private static final String UNICODE_FORMAT = "UTF8"; 

    public static String encrypt(String valueToEnc) throws Exception { 
Key key = generateKey(); 
Cipher c = Cipher.getInstance(ALGORITHM); 
c.init(Cipher.ENCRYPT_MODE, key); //////////LINE 20 
byte[] encValue = c.doFinal(valueToEnc.getBytes()); 
String encryptedValue = new BASE64Encoder().encode(encValue); 
return encryptedValue; 
    } 

public static String decrypt(String encryptedValue) throws Exception { 
Key key = generateKey(); 
Cipher c = Cipher.getInstance(ALGORITHM); 
c.init(Cipher.DECRYPT_MODE, key); 
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue); 
byte[] decValue = c.doFinal(decordedValue); 
String decryptedValue = new String(decValue); 
return decryptedValue; 
} 

private static Key generateKey() throws Exception { 
byte[] keyAsBytes; 
keyAsBytes = myEncryptionKey.getBytes(UNICODE_FORMAT); 
Key key = new SecretKeySpec(keyAsBytes, ALGORITHM); 
return key; 
} 

public static void main(String[] args) throws Exception { 

String value = "password1"; 
String valueEnc = AESEncryptionDecryptionTest.encrypt(value); 
String valueDec = AESEncryptionDecryptionTest.decrypt(valueEnc); 

System.out.println("Plain Text : " + value); 
System.out.println("Encrypted : " + valueEnc); 
System.out.println("Decrypted : " + valueDec); 
} 

} 
+0

какое заявление генерирует исключение? – aioobe

+0

c.init (Cipher.ENCRYPT_MODE, ключ); –

ответ

29

AES обеспечивает длину ключа 128, 192 или 256 бит. Это 16, 24 или 32 байт. Попробуйте взять только первые 16 байт вашего mEncryptionKey как keyAsBytes.

Редактировать:
После того, как произошло со мной. Привычка, которую я создал, и которую я рекомендую, заключается в том, чтобы взять хэш-код SHA пароля/парольной фразы и использовать это как исходные байты вашего ключа. Принимая хеш гарантирует, что ключевые данные будут иметь правильный размер, независимо от длины пароля/кодовой фразы. Ваша текущая реализация использования байтов String имеет две проблемы;

  • Это разрушит ваше поколение ключей, если кто-то использует короткий пароль.
  • Два разных пароля, для которых первые 16 байтов одинаковы, создадут один и тот же ключ.

Обе эти проблемы устраняются с помощью хэша.

Посмотрите на buildKey() метод в этом классе; https://github.com/qwerky/DataVault/blob/master/src/qwerky/tools/datavault/DataVault.java

+0

Спасибо Qwerky. Еще несколько находок. Когда я даю myEncryptionKey как 16-символьный длинный, то есть 128-битную длину, эта программа запускает штрафы, но когда я даю ей как 24 charecter long (длина 192 бит) или 32 символа (256-битная длина), тогда я получаю ошибку как " Недопустимый размер ключа или параметры по умолчанию ". Могу ли я установить длину ключа до 256 или 192, если я хочу? –

+1

Чтобы использовать 192 или 256, вам может потребоваться включить файлы политики «неограниченное количество ключей». Это связано с юридическими ограничениями в Соединенных Штатах. Глянь сюда; http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html. Найдите «Незаконный размер ключа или параметры по умолчанию» на этом сайте, есть несколько вопросов и ответов об этом. – Qwerky

+0

В вашем примере в Datavault.java используется BouncyCastleProvider, который не является стандартным классом java. Из-за некоторых ограничений мне нужно идти только со стандартными java-классами. Могу ли я использовать некоторую другую реализацию класса провайдера, установленного BouncyCastleProvider, в примере, который вы выбрали? –

1

Ключ использует случайность как входной сигнал, но существуют требования к stiill для того, как он состоит. Созданный вами конструктор SecretKeySpec предназначен для загрузки уже сгенерированного ключа в память. Вместо этого используйте KeyGenerator.

KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM); 
kg.init(128); 
SecretKey k = kg.generateKey(); 

Также обратите внимание, что теперь AES-128 считается более слабым, чем AES-256. Это, вероятно, не сильно отличается, но преимущество от более длительного размера ключа может быть перевешивается упрощениями в другом месте (меньше раундов).

+1

Привет, Джон. Я хочу использовать сам назначенный ключ, поскольку я буду использовать его как общий ключ. Я хочу использовать ключ, который известен и присваивается мной не сгенерированным системой ключом. Можете ли вы добавить некоторые входы, как я могу использовать самопривязанный ключ любой длины менее 256 бит в AES? –

Смежные вопросы