2012-05-31 6 views
11

Podczas uruchamiania poniżej programu otrzymuję ten wyjątek. Nie jesteś w stanie dowiedzieć się, na czym polega problem z AES, klucz 128-256-bitowy?Pierwsze wyjątek java.security.InvalidKeyException: niepoprawna długość klucza AES: 29 bajtów?

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*..) 

Uzyskiwanie wyjątek w wierszu 20

Oto program

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

które polecenie generuje wyjątek? – aioobe

+0

c.init (Cipher.ENCRYPT_MODE, klawisz); –

Odpowiedz

29

AES pozwala na 128, 192 lub 256 bitową długość klucza. To jest 16, 24 lub 32 bajty. Spróbuj zabrać tylko pierwszych 16 bajtów swojego telefonu mEncryptionKey jako keyAsBytes.

Edytuj:
Później jednak przyszło mi do głowy. Zwyczaj, który utworzyłem, i który polecam, to wziąć skrót SHA hasła/hasła, i użyć go jako bajtu źródłowego twojego klucza. Podanie wartości skrótu gwarantuje, że kluczowe dane będą miały prawidłowy rozmiar, niezależnie od długości hasła/hasła. Twoja obecna implementacja używania bajtów String ma dwa problemy;

  • To złamie twoją generację klucza, jeśli ktoś użyje krótkiego hasła.
  • Dwa różne hasła, dla których pierwsze 16 bajtów są takie same, utworzą ten sam klucz.

Oba te problemy zostały wyeliminowane za pomocą skrótu.

Spójrz na metodę buildKey() w tej klasie; https://github.com/qwerky/DataVault/blob/master/src/qwerky/tools/datavault/DataVault.java

+0

Dzięki Qwerky. Jeszcze więcej ustaleń. Kiedy podaję mójEncryptionKey jako 16-znakową długość, tj. 128-bitową długość, ten program uruchamia grzywnę, ale gdy podaję ją jako 24 charecter long (długość 192 bitów) lub 32-znakową (długość 256 bitów), wówczas otrzymuję błąd jako " Niedozwolony rozmiar klucza lub domyślne parametry ". Czy mogę ustawić długość klucza na 256 lub 192, jeśli chcę? –

+1

Aby użyć 192 lub 256, konieczne może być włączenie plików zasad "nieograniczonej siły klucza". Wynika to z ograniczenia prawnego w Stanach Zjednoczonych. Spójrz tutaj; http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html. Wyszukaj "Nielegalny rozmiar klucza lub domyślne parametry" na tej stronie, jest kilka pytań i odpowiedzi na ten temat. – Qwerky

+0

W twoim przykładzie w Datavault.java użyto BouncyCastleProvider, który nie jest standardową klasą java. Z powodu pewnych ograniczeń muszę iść tylko ze standardowymi klasami java. Czy mogę użyć innej implementacji klasy dostawcy instancji BouncyCastleProvider w podanym przykładzie? –

1

Klucz wykorzystuje losowość jako dane wejściowe, ale istnieją pewne wymagania dotyczące sposobu jego komponowania. Konstruktorem SecretKeySpec, którego użyłeś, jest ładowanie już wygenerowanego klucza do pamięci. Zamiast tego użyj KeyGenerator.

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

Należy również zauważyć, że AES-128 jest obecnie uważany za słabszy niż AES-256. Prawdopodobnie nie jest drastycznie odmienny, ale korzyści wynikające z dłuższego klucza mogą być przeważone przez uproszczenia w innym miejscu (mniej rund).

+1

Cześć John. Chcę użyć przypisanego do siebie klucza, ponieważ będę używać jako klucza dzielonego. Chcę użyć klucza, który jest znany i przypisany przeze mnie, a nie klucza wygenerowanego przez system. Czy możesz rzucić niektóre dane wejściowe, w jaki sposób mogę użyć przypisanego do siebie klucza o długości mniejszej niż 256 bitów w AES? –