2016-09-13 2 views
4

내 앱에서 초기 설정 [지문 등록]에서 손가락을 스캔 할 때 암호화 된 버전의 사용자 액세스 코드를 저장합니다. 사용자가 나중에 앱을 잠금 해제하려고하면 Fingerprint API [지문 인증]을 사용하여이 액세스 코드의 암호를 해독하려고 시도합니다.Fingerprint API 암호 해독을 시도 할 때 BadPaddingException

그러나 Cipher.doFinal 해독에 다음과 같은 예외가 발생 :

javax.crypto.BadPaddingException 
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:482) 
at javax.crypto.Cipher.doFinal(Cipher.java:1502) 
(...) 

Caused by: android.security.KeyStoreException: Invalid argument 
     at android.security.KeyStore.getKeyStoreException(KeyStore.java:940) 
     at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224) 
     at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:473) 
     ... 12 more 

지문 스캐너는 DialogFragment 표시된다. 다음 함수는 지문 등록 또는 검증 여부와 관계없이 항상 생성자 순서대로 호출됩니다.

키 스토어 초기화 : 만들기

private void initializeKeystore() { 

    try { 
     mKeyStore = KeyStore.getInstance(KEY_STORE_NAME); //AndroidKeyStore 
    } catch (KeyStoreException e) { 
     mKeyStore = null; 
    } 

    try { 
     mKeyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEY_STORE_NAME); 
    } catch (NoSuchAlgorithmException | NoSuchProviderException e) { 
     mKeyGenerator = null; 
    } 
} 

을 핵심 다음 지문 스캐너 API가 성공적으로 사용자를 인증 할 때

private void createCipher() { 
    try { 
     mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" 
       + KeyProperties.BLOCK_MODE_CBC + "/" 
       + KeyProperties.ENCRYPTION_PADDING_PKCS7); 
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { 
     mCipher = null; 
    } 
} 

, 다음

private void createKey() { 
    if (mKeyGenerator != null) { 
     try { 
      mKeyStore.load(null); 

      KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(KEY_NAME, 
        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 
        .setBlockModes(KeyProperties.BLOCK_MODE_CBC) 
        .setUserAuthenticationRequired(true) 
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7); 

      mKeyGenerator.init(builder.build()); 
      mKeyGenerator.generateKey(); 
     } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | 
       CertificateException | IOException e) { 
      mKeyGenerator = null; 
     } 
    } 
} 

이 암호 객체를 생성 코드가 순서대로 호출됩니다.

바로 이전 호출에서 반환 된 암호의 인스턴스를 사용
@Nullable Cipher getCipher(@NonNull final FingerprintStore ivStore) { 
    if (mKeyStore != null && mKeyGenerator != null && mCipher != null) { 
     try { 
      mKeyStore.load(null); 
      SecretKey key = (SecretKey)mKeyStore.getKey(KEY_NAME, null); 

      switch (mEncryptionMode) { 
       case MODE_ENCRYPT: 
        mCipher.init(Cipher.ENCRYPT_MODE, key); 
        ivStore.writeIv(mCipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV()); 
        break; 
       case MODE_DECRYPT: 
        byte[] iv = ivStore.readIv(); 
        mCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); 
        break; 
      } 
      return mCipher; 
     } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException 
       | NoSuchAlgorithmException | InvalidKeyException | InvalidAlgorithmParameterException 
       | InvalidParameterSpecException | NullPointerException e) { 
      return null; 
     } 
    } 

    return null; 
} 

그리고, : doFinal

@Nullable byte[] encryptOrDecrypt(@NonNull Cipher cipher, @NonNull byte[] subject) { 
    try { 
     return cipher.doFinal(subject); 
    } catch (BadPaddingException | IllegalBlockSizeException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 

이 호출은 데이터를 암호화 할 때 잘 작동하지만 암호 해독에 예외가 발생합니다. 난 byte[]의 초기화 벡터와 암호화 된 데이터를 검사하고 그들이 디스크 (Base64)에 저장되고 다시 메모리에 올바르게 읽혀 있음을 발견했습니다.

답변

4

신경 쓰지 마라. 분명히 SecretKey은 등록 단계에서만 생성되어야한다는 사실을 간과했다. 데이터를 해독하려고 시도 할 때 createKey이 호출되었으므로 doFinal이 호출되기 전에 새로 생성 된 키로 덮어 씁니다. 코드가 완벽하게 작동합니다.

관련 문제