2014-12-02 51 views
7

Mam następujące funkcje szyfrowania/odszyfrowywania javascript oparte na cryptojs, który działa idealnie dobrze.Jak odszyfrować szyfrowaną wiadomość AES kryptograficzną po stronie serwera Java?

Używam losowej soli, losowej wartości iv i określonego hasła podczas szyfrowania wiadomości za pomocą cryptpjs. Ponownie używam tej samej soli, iv i hasła, aby wygenerować klucz podczas odszyfrowywania zaszyfrowanej wiadomości.

Ta część działa dobrze ..

function encrypt(){ 
    var salt = CryptoJS.lib.WordArray.random(128/8); 
    var iv = CryptoJS.lib.WordArray.random(128/8); 
    console.log('salt '+ salt); 
    console.log('iv '+ iv); 
    var key128Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32 }); 
    console.log('key128Bits '+ key128Bits); 
    var key128Bits100Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32, iterations: 100 }); 
    console.log('key128Bits100Iterations '+ key128Bits100Iterations); 
    var encrypted = CryptoJS.AES.encrypt("Message", key128Bits100Iterations, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); 
    console.log('encrypted '+ encrypted ); 
} 

function decrypt(){ 
    var salt = CryptoJS.enc.Hex.parse("4acfedc7dc72a9003a0dd721d7642bde"); 
    var iv = CryptoJS.enc.Hex.parse("69135769514102d0eded589ff874cacd"); 
    var encrypted = "PU7jfTmkyvD71ZtISKFcUQ=="; 
    console.log('salt '+ salt); 
    console.log('iv '+ iv); 
    var key = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32, iterations: 100 }); 
    console.log('key '+ key); 
    var decrypt = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); 
    var ddd = decrypt.toString(CryptoJS.enc.Utf8); 
    console.log('ddd '+ddd); 
} 

Ale problem zaczyna się, gdy próbuję odszyfrować ten sam zaszyfrowany tekst na stronie serwera Java. Chcę, aby zaszyfrowana wiadomość została odszyfrowana przez mój kod serwera java. Oto kod Java, który napisałem:

public static void main(String args[]) throws Exception{ 
    String password = "Secret Passphrase"; 
    String salt = "4acfedc7dc72a9003a0dd721d7642bde"; 
    String iv = "69135769514102d0eded589ff874cacd"; 
    String encrypted = "PU7jfTmkyvD71ZtISKFcUQ=="; 
    byte[] saltBytes = salt.getBytes(); //hexStringToByteArray(salt); 
    byte[] ivBytes = iv.getBytes();//hexStringToByteArray(iv); 
    IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);   
    SecretKeySpec sKey = (SecretKeySpec) generateKeyFromPassword(password, saltBytes); 
    System.out.println(decrypt(encrypted , sKey ,ivParameterSpec)); 
} 

public static SecretKey generateKeyFromPassword(String password, byte[] saltBytes) throws GeneralSecurityException { 

    KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes, 100, 128/32); 
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    SecretKey secretKey = keyFactory.generateSecret(keySpec); 
    return new SecretKeySpec(secretKey.getEncoded(), "AES"); 
} 

public static String decrypt(String encryptedData, SecretKeySpec sKey, IvParameterSpec ivParameterSpec) throws Exception { 

    Cipher c = Cipher.getInstance("AES"); 
    c.init(Cipher.DECRYPT_MODE, sKey, ivParameterSpec); 
    byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); 
    byte[] decValue = c.doFinal(decordedValue); 
    String decryptedValue = new String(decValue); 
    return decryptedValue; 
} 

Ale pojawia się następujący wyjątek:

Exception breakpoint: SecretKeySpec.java:96, java.lang.IllegalArgumentException, Empty key 
Exception in thread "main" java.lang.IllegalArgumentException: Empty key 
at javax.crypto.spec.SecretKeySpec.<init>(SecretKeySpec.java:96) 

nie mam pojęcia co mam zrobić

Odpowiedz

7

Ta część kodu jest źle :

KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes, 100, 128/32); 
//->---------------------------------------------------------------------^^^^^^^ 

Wartość 128/32 jest błędna. Potrzebujesz albo 128, 192 lub 256. Obecnie masz odpowiednik 4, który wydaje się nie generować żadnego wyjścia z funkcji PBKDF2.

Również w Javie powinieneś użyć DatatypeConverter.parseHexBinary() lub podobnego, aby przekonwertować hex na bajty. Aktualnie dzwonisz pod numer getBytes(), co nie jest poprawne.

Na koniec należy określić tryb CBC i dopełnienie PKCS # 5, aby dopasować kod JavaScript. Zmień linię na:

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
+1

Moment zrobiłem zmiany sugerowane, to działało. Dzięki, Duncan. Dostarczę kompletne rozwiązanie robocze jako kolejną odpowiedź. Dzięki stosy. Byłeś na miejscu i naprawiłeś moje problemy. – user1455719

6

Podziękowania dla Duncana za szybką odpowiedź i porady. Daję pełne rozwiązanie, które działało dla mnie poniżej, z korzyścią dla innych.

kod Java zrobić deszyfrowania cryptojs zaszyfrowana wiadomość

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

String password = "Secret Passphrase"; 
String salt = "222f51f42e744981cf7ce4240eeffc3a"; 
String iv = "2b69947b95f3a4bb422d1475b7dc90ea"; 
String encrypted = "CQVXTPM2ecOuZk+9Oy7OyGJ1M6d9rW2D/00Bzn9lkkehNra65nRZUkiCgA3qlpzL"; 

byte[] saltBytes = hexStringToByteArray(salt); 
byte[] ivBytes = hexStringToByteArray(iv); 
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);   
SecretKeySpec sKey = (SecretKeySpec) generateKeyFromPassword(password, saltBytes); 
System.out.println(decrypt(encrypted , sKey ,ivParameterSpec)); 

} 

public static SecretKey generateKeyFromPassword(String password, byte[] saltBytes) throws GeneralSecurityException { 

KeySpec keySpec = new PBEKeySpec(password.toCharArray(), saltBytes, 100, 128); 
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
SecretKey secretKey = keyFactory.generateSecret(keySpec); 

return new SecretKeySpec(secretKey.getEncoded(), "AES"); 
} 

public static byte[] hexStringToByteArray(String s) { 

int len = s.length(); 
byte[] data = new byte[len/2]; 

for (int i = 0; i < len; i += 2) { 
    data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 
    + Character.digit(s.charAt(i+1), 16)); 
} 

    return data; 

} 

public static String decrypt(String encryptedData, SecretKeySpec sKey, IvParameterSpec ivParameterSpec) throws Exception { 

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
c.init(Cipher.DECRYPT_MODE, sKey, ivParameterSpec); 
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); 
byte[] decValue = c.doFinal(decordedValue); 
String decryptedValue = new String(decValue); 

return decryptedValue; 
} 
+0

Użyłem twojego kodu Javascript (o którym mowa) i kodu Java (w tej odpowiedzi) jako przykładu i zaimplementowałem go. Kod Java z powodzeniem działa, gdy hasło, sól, iv i zaszyfrowane są zakodowane tak jak w tej odpowiedzi. Użyłem również kodu javascript po stronie klienta, ale wygląda na to, że po stronie js istnieją pewne błędne konfiguracje, takie jak rozmiar klucza i tak dalej, ponieważ podczas dekodowania danych zakodowanych w javascript dostaję zły wyjątek padding w java. Czy możesz podać działający kod javascript .. –

+0

Jest to błąd "Biorąc pod uwagę błąd Ostateczny blok nieprawidłowo dopełniony" w java –