2011-06-30 21 views
11

Jestem nowy w technologii szyfrowania. Znalazłem ten kod do wykonania szyfrowania symetrycznego.Java przy użyciu szyfrowania AES 256 i 128 Symetryczny klucz szyfrowania

byte[] key = //... secret sequence of bytes 
byte[] dataToSend = ... 
Cipher c = Cipher.getInstance("AES"); 
SecretKeySpec k = new SecretKeySpec(key, "AES"); 
c.init(Cipher.ENCRYPT_MODE, k); 
byte[] encryptedData = c.doFinal(dataToSend); 

Działa. Tutaj mogę użyć własnego hasła. I tego właśnie potrzebowałem. Ale nie wiem jak zrobić 128 lub 256 Symetryczna Enctryption. Jak mogę użyć klucza 128 i 256 w moim kodzie?

+0

ja naprawdę nie wiem, ale myślę, że za pomocą klucza 256 bajtów będzie wykonać zadanie. –

+0

faktycznie tylko 16-bajtowy (128-bitowy) klucz działa w moim kodzie. – Bhuban

+0

co oznacza "nie działa" przy większych kluczach? Czy otrzymujesz wyjątek? Który? jaka jest jego wiadomość i ślad stosu? –

Odpowiedz

13

To, czy AES używa trybu 128, czy 256-bitowego, zależy od wielkości klucza, który musi mieć 128 lub 256 bitów. Zwykle nie używasz hasła jako klucza, ponieważ hasła rzadko mają dokładnie taką długość, jakiej potrzebujesz. Zamiast tego uzyskujesz klucz szyfrujący ze swojego hasła za pomocą funkcji wyprowadzania klucza.

Bardzo prosty przykład: weź MD5 swojego hasła, aby uzyskać klucz 128-bitowy. Jeśli potrzebujesz klucza 256-bitowego, możesz użyć SHA-256, aby uzyskać 256-bitowy skrót hasła. Funkcje derywacji kluczy zwykle uruchamiają to mieszanie kilkaset razy i używają również dodatkowej soli. Aby uzyskać szczegółowe informacje, sprawdź numer http://en.wikipedia.org/wiki/Key_derivation_function.

Uwaga: aby szyfrowanie było wydajniejsze niż 128-bitowe, należy pobrać i zainstalować "Pliki zasad jurysdykcji Java Cryptography Extension (JCE) 6" z http://www.oracle.com/technetwork/java/javase/downloads/index.html.

+5

MD5? Czy obudziłem się rano w 1996 roku? Rodzina algorytmów SHA ma algorytmy generujące 128, 256, 348 i 512 bitów. –

+4

@Peter: to był tylko szybki przykład jak zdobyć klucz 128-bitowy obliczony z hasła. Jeśli twoje hasło ma mniej niż 16 bajtów, możesz równie dobrze ustawić go na 16 bajtów. Czerpiesz nieistotne szczegóły. (W każdym razie zaktualizowałem swoją odpowiedź, aby użyć SHA-256 do uzyskania klucza 256-bitowego z hasła) –

+1

@Peter, hahaha, tak po prostu nienawidzę widząc MD5 w niczym innym niż kod źródłowym, i nie sądzę, że powinno to być zalecane dla początkujących; Już dawno zostało złamane. –

2

Można użyć prostego KeyGenerator obiektu takiego:

KeyGenerator generator = KeyGenerator.getInstance("AES/CTR/PKCS5PADDING"); 
generator.init(128); 
SecretKey key = generator.generateKey(); 
Cipher cipher = Cipher.getInstance("AES"); 
cipher.init(Cipher.ENCRYPT_MODE, key); 
... 
+1

. Jak mogę użyć własnego hasła? – Bhuban

1

Od Java's docs for Cipher.init(...):

public final void init (int opmode, Klawisz)

Zgłasza: InvalidKeyException - jeśli podany klucz jest nieodpowiedni do zainicjowania tego szyfrowania lub jeśli ten szyfr to inicjowany do deszyfrowania i wymaga parametrów algorytmu, który nie można ustalić z danego klucza lub jeśli dany klucz ma rozmiar klucza która przekracza maksymalną dopuszczalną rozmiar klucza (jak określono na podstawie skonfigurowanych plików zasad jurysdykcji).

Dla mnie oznacza to, że, jak Martijn Courteaux powiedział w swoim komentarzu, należy użyć klucza 256 bitów (czyli zainicjować SecretKeySpec z tablicy bajtów zawierającego 32 bajtów), a szyfr będzie go zaakceptować i użyj go lub odrzuć i wyrzuć wyjątek, jeśli jego rozmiar nie jest akceptowalny.

Jeśli otrzymasz wyjątek, prawdopodobnie jest tak, ponieważ nie zainstalowałeś plików kryptograficznych o nieograniczonej sile (domyślna instalacja JDK pozwala na 128-bitowe klucze, jak udokumentowano w tym crypto spec document). Pobierz pakiet crypto o nieograniczonej sile here.

+0

Tak, mój kod może mieć dokładnie 16 bajtów lub 128 bitów. Więc to było moje pytanie, jak używać klucza 256-bitowego? – Bhuban

+0

Edytowałem moją odpowiedź –

+0

Dzięki. Już działa. Twoja odpowiedź była bardzo pomocna. – Bhuban

0
public class CipherUtils 
{ 
    private static byte[] key = { 
      0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 
    };//"thisIsASecretKey"; 

    public static String encrypt(String strToEncrypt) 
    { 
     try 
     { 
      Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 
      final SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
      cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
      final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes())); 
      return encryptedString; 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 
+0

Mam kilka pytań. 1. Ten klucz jest jedynym kluczem, który może zostać użyty do odszyfrowania, prawda? (prawdopodobnie oczywista odpowiedź na to pytanie - tylko upewnienie się) 2. Jeśli te same dane są szyfrowane przy użyciu tego samego klucza - dwa razy uruchamiając metodę - czy renderuje różne zaszyfrowane bajty? – raddevus

+0

Cóż, przekonwertowałem ten kod i wymyśliłem odpowiedzi dla siebie. Co ciekawe, przykład OWASP (https://www.owasp.org/index.php/Using_the_Java_Cryptographic_Extensions) bezpośrednio wspomina użycie IV (wektor inicjalizacyjny), ale nie jest użyty w kodzie w tej odpowiedzi. Ce la vie. – raddevus

+0

Nie twórz sztywnego kodu tajnego klucza. Będzie trywialnie dostępny dla każdego, kto ma dostęp do skompilowanego kodu. – Mike

6

odpowiedź dla 128 bitów

Poniższa metoda jest do zaszyfrowania ciąg (valueEnc) z szyfrowaniem AES:

private static final String ALGORITHM = "AES"; 

public String encrypt(final String valueEnc, final String secKey) { 

    String encryptedVal = null; 

    try { 
     final Key key = generateKeyFromString(secKey); 
     final Cipher c = Cipher.getInstance(ALGORITHM); 
     c.init(Cipher.ENCRYPT_MODE, key); 
     final byte[] encValue = c.doFinal(valueEnc.getBytes()); 
     encryptedVal = new BASE64Encoder().encode(encValue); 
    } catch(Exception ex) { 
     System.out.println("The Exception is=" + ex); 
    } 

    return encryptedVal; 
} 

Kolejna metoda odszyfrować zaszyfrowany ciąg AES (encryptedVal) :

public String decrypt(final String encryptedValue, final String secretKey) { 

    String decryptedValue = null; 

    try { 

     final Key key = generateKeyFromString(secretKey); 
     final Cipher c = Cipher.getInstance(ALGORITHM); 
     c.init(Cipher.DECRYPT_MODE, key); 
     final byte[] decorVal = new BASE64Decoder().decodeBuffer(encryptedValue); 
     final byte[] decValue = c.doFinal(decorVal); 
     decryptedValue = new String(decValue); 
    } catch(Exception ex) { 
     System.out.println("The Exception is=" + ex); 
    } 

    return decryptedValue; 
} 

The secKey to 128-bitowy klucz, który jest zakodowany w BASE64Encoder. BASE64Decoder w następujący sposób generuje odpowiedni 128-bitowy klucz

private Key generateKeyFromString(final String secKey) throws Exception { 
    final byte[] keyVal = new BASE64Decoder().decodeBuffer(secKey); 
    final Key key = new SecretKeySpec(keyVal, ALGORITHM); 
    return key; 
} 
+1

Zapomniałeś użyć wektora inicjującego, a także nie określiłeś trybu i dopełnienia AES, którego chcesz użyć. Chociaż jest to odpowiedź na pytanie, należy pamiętać, że to ** nie ** bezpieczne korzystanie z szyfrowania. –

Powiązane problemy