2016-07-12 21 views
0

Versucht, einige Daten zu verschlüsseln und zu entschlüsseln, auf Marshmallow. Die Verschlüsselung funktioniert gut, aber wenn ich versuche zu entschlüsseln, bekomme ich eine RuntimeException und sage "iv == null".Android Cipher AES/GCM/NoPadding "iv == null"

Grundsätzlich geben cipher.getIV() und cipher.getParameters() null zurück. Fehle ich etwas?

private static final String ALGORITHM_NAME = "AES/GCM/NoPadding"; 
    private static final int IV_SIZE = 128; 
    private static final int ALGORITHM_SIZE = 256; 

    private static final String KEYSTORE_PROVIDER = "AndroidKeyStore"; 
    private static final String SYMMETRIC_ALIAS = "secret_key"; 

    private static SecretKey getSymmetricKey() 
     throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, 
     CertificateException, KeyStoreException, UnrecoverableEntryException { 

    KeyStore ks = KeyStore.getInstance(KEYSTORE_PROVIDER); 
    ks.load(null); 

    return (SecretKey) ks.getKey(SYMMETRIC_ALIAS, null); 
    } 

    private static SecretKey createSecretKey() 
     throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { 

    KeyGenerator keyGenerator = KeyGenerator.getInstance(
     KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER); 

    keyGenerator.init(new KeyGenParameterSpec.Builder(SYMMETRIC_ALIAS, 
     KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 
     .setBlockModes(KeyProperties.BLOCK_MODE_GCM) 
     .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) 
     .setKeySize(ALGORITHM_SIZE) 
     .setRandomizedEncryptionRequired(true) 
     .setUserAuthenticationRequired(false) 
     .build()); 

    return keyGenerator.generateKey(); 
    } 

    public static byte[] encrypt(byte[] data) 
     throws CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableEntryException, 
     KeyStoreException, NoSuchProviderException, InvalidAlgorithmParameterException, NoSuchPaddingException, 
     InvalidKeyException, BadPaddingException, IllegalBlockSizeException { 

    SecretKey secretKey = getSymmetricKey(); 
    if (secretKey == null) { 
     secretKey = createSecretKey(); 
    } 

    Cipher cipher = Cipher.getInstance(ALGORITHM_NAME); 
    cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
    return cipher.doFinal(data); 
    } 

    public static byte[] decrypt(byte[] data) 
     throws CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableEntryException, 
     KeyStoreException, NoSuchProviderException, InvalidAlgorithmParameterException, NoSuchPaddingException, 
     InvalidKeyException, BadPaddingException, IllegalBlockSizeException { 

    SecretKey secretKey = getSymmetricKey(); 

    Cipher cipher = Cipher.getInstance(ALGORITHM_NAME); 
    GCMParameterSpec spec = new GCMParameterSpec(IV_SIZE, cipher.getIV()); 
    cipher.init(Cipher.DECRYPT_MODE, secretKey, spec); 
    return cipher.doFinal(data.getBytes()); 
    } 

Antwort

3

Sie müssen einen Nicht-Null-IV AES/GCM/NoPadding Cipher.init zu liefern, wenn die Entschlüsselung. Ihr Code bietet jedoch eine null IV, die durch Aufrufen von Cipher.getIV() auf einer nicht initialisierten Cipher Instanz erhalten wird.

Die Lösung besteht darin, die beim Verschlüsseln verwendete IV zu speichern und dann dieselbe gespeicherte IV beim Entschlüsseln zu verwenden.

+1

Die IV muss nicht geheim sein, aber sie muss für GCM eindeutig sein. Da es immer die gleiche Länge hat, können Sie es einfach dem Chiffretext voranstellen und vor der Entschlüsselung abschneiden. –