2016-07-12 6 views
0

マシュマロで一部のデータの暗号化と復号化を試みています。暗号化はうまくいくが、解読しようとすると "iv == null"というRuntimeExceptionが出る。Android Cipher AES/GCM/NoPadding "iv == null"

基本的に、cipher.getIV()およびcipher.getParameters()はnullを返します。 何か不足していますか?

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

答えて

3

あなたは、復号化の際AES/GCM/NoPadding Cipher.initにnull以外のIVを提供する必要があります。ただし、コードにnull IVがあり、初期化されていないCipherインスタンスでCipher.getIV()を呼び出して取得します。

暗号化時に使用したIVを保存し、復号化時に同じ保存IVを使用するように修正しました。

+1

IVは秘密である必要はありませんが、GCMでは一意である必要があります。常に同じ長さになっているので、単純に暗号文の前に付加して暗号化解除してから解読することができます。 –