2016-07-12 3 views
0

마시맬로에서 일부 데이터를 암호화하고 해독하려고합니다. 암호화는 잘 작동하지만 해독하려고하면 "iv == null"이라고 RuntimeException이 발생합니다.Android Cipher AES/GCM/NoPadding "iv == null"

기본적으로 cipher.getIV() 및 cipher.getParameters()는 null을 반환합니다. 내가 빠진 것이 있습니까? 당신은 해독 할 때 AES/GCM/NoPadding Cipher.init에 null이 아닌 IV를 제공하기 위해해야 ​​

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

. 그러나 코드에서 초기화되지 않은 Cipher 인스턴스에서 Cipher.getIV()을 호출하여 얻은 null IV를 제공합니다.

해결 방법은 암호화 할 때 사용 된 IV를 저장 한 다음 해독 할 때 동일한 IV를 저장하는 것입니다.

+1

IV는 비밀 일 필요는 없지만 GCM에는 고유해야합니다. 길이가 항상 같으므로 해독 전에 암호문 앞에 붙여 넣기 만하면됩니다. –