2015-10-19 9 views
11

Sto seguendo l'esempio di Android fornito da Google, ConfirmCredential, ma mostra solo come crittografare i dati. Quando provo a decifrarlo ottengo un'eccezione:Problema durante l'utilizzo dell'impronta digitale Android: richiesta IV durante la decrittografia. Utilizza IvParameterSpec o AlgorithmParameters per fornirlo

java.security.InvalidKeyException: IV required when decrypting. Use IvParameterSpec or AlgorithmParameters to provide it. 

Io uso il seguente codice:

String transforation = KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7; 

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 
keyStore.load(null); 
SecretKey secretKey = (SecretKey) keyStore.getKey(KEY_NAME, null); 

// encrypt 
Cipher cipher = Cipher.getInstance(transforation); 
cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
String encriptedPassword = cipher.doFinal("Some Password".getBytes("UTF-8")); 

// decrypt 
cipher = Cipher.getInstance(transforation); 
cipher.init(Cipher.DECRYPT_MODE, secretKey); 
String password = new String(cipher.doFinal(encriptedPassword), "UTF-8")); 

viene generata l'eccezione alla riga:

cipher.init(Cipher.DECRYPT_MODE, secretKey); 

Qualche idea su quello che è il modo corretto di fare la decrittazione in questo caso?

+1

Consulta http://stackoverflow.com/questions/6669181/why-does-my-aes-encryption-throws-an-invalidkeyexception e verifica se l'utilizzo di IvParameterSpec è utile. – ditkin

+0

Cancella duplicato IMHO. – JimmyB

+0

@ditkin Avevo già provato ad aggiungere IV, ma risultava con eccezione: java.security.InvalidAlgorithmParameterException: IV fornito dal chiamante non consentito durante la crittografia. – Zlatko

risposta

10

In pratica dovete passare l'IvParameterSpec per la modalità di decifrare, mentre non si dovrebbe impostare manualmente per modalità di crittografia.

ecco quello che ho fatto e ha funzionato bene:

private initCipher(int mode) { 
    try { 
     byte[] iv; 
     mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" 
       + KeyProperties.BLOCK_MODE_CBC + "/" 
       + KeyProperties.ENCRYPTION_PADDING_PKCS7); 
     IvParameterSpec ivParams; 
     if(mode == Cipher.ENCRYPT_MODE) { 
      mCipher.init(mode, generateKey()); 
      ivParams = mCipher.getParameters().getParameterSpec(IvParameterSpec.class); 
      iv = ivParams.getIV(); 
      fos = getContext().openFileOutput(IV_FILE, Context.MODE_PRIVATE); 
      fos.write(iv); 
      fos.close(); 
     } 
     else { 
      key = (SecretKey)keyStore.getKey(KEY_NAME, null); 
      File file = new File(getContext().getFilesDir()+"/"+IV_FILE); 
      int fileSize = (int)file.length(); 
      iv = new byte[fileSize]; 
      FileInputStream fis = getContext().openFileInput(IV_FILE); 
      fis.read(iv, 0, fileSize); 
      fis.close(); 
      ivParams = new IvParameterSpec(iv); 
      mCipher.init(mode, key, ivParams); 
     } 
     mCryptoObject = new FingerprintManager.CryptoObject(mCipher); 
    } catch(....) 
} 

È anche possibile codificare i dati IV con Base64 e salvarlo con le preferenze condivise invece di salvarlo in un file.

In entrambi i casi, se si hanno impiegato la nuova funzionalità di backup completo per Android M, tenere a mente che questi dati dovrebbe NON essere consentito di backup/ripristino dal momento che non è valido quando un utente reinstallare l'applicazione o installare il app su un altro dispositivo.

+0

Questo mi ha salvato la vita. Grazie. : D – WonderKid

0

Come su questo,

mCipher.init(Cipher.DECRYPT_MODE, key, mCipher.getParameters());

Se si utilizza il codice di esempio da parte di Google di pronti contro termine, sopra la linea funzionerà, nota anche, per ogni mChiper.init abbiamo bisogno di autenticazione con impronte digitali, una volta, che i mezzi sono richieste due impronte digitali, una per la crittografia e una per la decrittografia.

https://github.com/googlesamples/android-FingerprintDialog

+0

Grazie per il feedback, ma ancora una volta è risultato con java.security.InvalidAlgorithmParameterException: richiesto IV durante la decrittografia. Usa IvParameterSpec o AlgorithmParameters per fornirlo. Io uso https: // github.it/googlesamples/android-ConfirmCredential e AUTHENTICATION_DURATION_SECONDS impostato su 30, quindi mi aspetto che sarà necessaria solo una volta la scansione delle impronte digitali. – Zlatko

4

ho creato un problema nel progetto github per il campione fornito da Google (link alla questione here). La risposta che ho ottenuto è che devo usare il IV che è stato generato quando il valore è stato crittografato. (Identico a quello della soluzione fornita da @Qianqian)

cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(encryptCipher.getIV())); 
byte[] decryptedBytes = cipher.doFinal(encryptedBytes); 

Ho generato un'applicazione di esempio che illustra come eseguire questa operazione. È disponibile su github, here.

Spero che questo sia utile a qualcuno.