2016-07-12 52 views
0

嘗試在棉花糖上加密和解密一些數據。加密效果很好,但是當試圖解密時,我得到一個RuntimeException,說「iv == null」。Android密碼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,通過在未初始化的Cipher實例上調用Cipher.getIV()獲得。

解決的辦法是保存加密時使用的IV,然後在解密時使用該保存的IV。

+1

IV並不需要保密,但它對GCM必須是唯一的。由於它的長度始終相同,因此您可以簡單地將其預先加密至密文,並在解密之前將其切斷。 –