2014-12-02 22 views
7

Ho le seguenti funzioni di crittografia/decrittografia javascript basate su cryptojs che funziona perfettamente bene.Come decrittografare un messaggio crittografato AES di cryptojs dal lato del server java?

Uso un valore casuale di sale, valore iv casuale e una password specifica durante la crittografia del messaggio utilizzando cryptpjs. Riuso lo stesso sale, iv e la password per generare la chiave durante la decrittografia del messaggio crittografato.

Questa parte funziona bene ..

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

Ma il problema inizia quando cerco di decifrare lo stesso testo cifrato al lato server Java. Desidero che il messaggio crittografato venga decifrato dal mio codice java server. Ecco il codice Java che ho scritto:

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

ma ottengo la seguente eccezione:

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) 

Non ho idea di che cosa devo fare

risposta

7

Questa parte del codice è sbagliato :

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

Il valore 128/32 è errato. Avete bisogno di 128, 192 o 256. Attualmente hai l'equivalente di 4, che sembra non produrre alcun output dalla funzione PBKDF2.

Inoltre, in Java è necessario utilizzare DatatypeConverter.parseHexBinary() o simile per convertire hex in byte. Attualmente stai chiamando solo getBytes() che non è giusto.

Infine, è necessario specificare la modalità CBC e il riempimento PKCS # 5 per far corrispondere il codice Javascript. Quindi cambia la linea in:

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

Nel momento in cui ho fatto le modifiche suggerite, ha funzionato. Grazie Duncan. Fornirò la soluzione di lavoro completa come un'altra risposta. Grazie mille. Tu eri azzeccato e hai risolto i miei problemi. – user1455719

6

Grazie a Duncan per la pronta risposta e il consiglio. Sto dando la soluzione completa che ha funzionato per me qui sotto a beneficio degli altri.

codice Java per fare la decrittografia dei cryptojs messaggio cifrato

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

Ho usato il codice Javascript (in questione) e il codice Java (in questa risposta) come esempio e l'ho implementato. Il codice Java funziona correttamente quando la password, salt, iv e criptati sono codificati come in questa risposta. Ho anche usato il tuo codice javascript per il lato client, ma sembra che ci siano alcune errate configurazioni nel lato js come le dimensioni della chiave e così via, perché ne sto ricevendo un'eccezione di padding errata in java quando decodifica i dati codificati javascript. Puoi fornire il codice javascript funzionante .. –

+0

È "Errore di blocco finale non corretto" in java –

Problemi correlati