KeyPermanentlyInvalidatedException не работает

Я использовал KeyPermanentlyInvalidatedException для обнаружения добавления нового отпечатка пальца. Но это не выдает KeyPermanentlyInvalidatedException.

Я попробовал эти шаги:

  1. Элемент списка
  2. Создать пару ключей
  3. Init Подпись с закрытого ключа
  4. Добавить новый отпечаток из настроек телефона
  5. Попробуй Init Signature из закрытого ключа еще раз, но он не выдает KeyPermanentlyInvalidatedException

Я также нашел эту ссылку из stackru, но она мне не помогла.

Из документа:

Ключ станет необратимо недействительным после того, как будет отключен экран безопасной блокировки (перенастроен на режим "Нет", "Размах" или другой режим, который не аутентифицирует пользователя), или когда экран безопасной блокировки принудительно сбрасывается (например, администратором устройства). Кроме того, если ключ требует, чтобы аутентификация пользователя выполнялась при каждом использовании ключа, он также необратимо аннулируется после регистрации нового отпечатка пальца или после того, как не зарегистрировано больше отпечатков пальцев, если только setInvalidatedByBiometricEnrollment(логическое значение) не используется для обеспечения допустимости после регистрации. Попытки инициализировать криптографические операции с использованием таких ключей приведут к возникновению KeyPermanentlyInvalidatedException.

Вот мой код:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_authenticate);

    mButtonTest = findViewById(R.id.button_test);
    mButtonTest.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            buttonTestOnClick();
        }
    });

    boolean isFirstTime = PreferenceManager.getInstances().getFirstTime();
    PreferenceManager.getInstances().setFirstTime(false);

    if (isFirstTime) {
        createKeyPair();
    }
}

private void buttonTestOnClick() {
    boolean result = initSignature();
    Log.e("iii", "Create signature result: " + result);

    boolean isFirstTime = PreferenceManager.getInstances().getFirstTime();

    if (result) {
        if (isFirstTime) {
            enroll();
        }
        startListening();
    }
}


/**
 * Generates an asymmetric key pair in the Android Keystore. Every use of the private key must
 * be authorized by the user authenticating with fingerprint. Public key use is unrestricted.
 */
public void createKeyPair() {
    try {
        mKeyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
    } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
        throw new RuntimeException("Failed to get an instance of KeyPairGenerator", e);
    }

    // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
    // for your flow. Use of keys is necessary if you need to know if the set of
    // enrolled fingerprints has changed.
    try {
        // Set the alias of the entry in Android KeyStore where the key will appear
        // and the constrains (purposes) in the constructor of the Builder
        mKeyPairGenerator.initialize(
                new KeyGenParameterSpec.Builder(KEY_NAME,
                        KeyProperties.PURPOSE_SIGN)
                        .setDigests(KeyProperties.DIGEST_SHA256)
                        .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
                        // Require the user to authenticate with a fingerprint to authorize
                        // every use of the private key
                        .setUserAuthenticationRequired(true)
                        .build());
        mKeyPairGenerator.generateKeyPair();
    } catch (InvalidAlgorithmParameterException e) {
        throw new RuntimeException(e);
    }
}


/**
 * Initialize the {@link Signature} instance with the created key in the
 * {@link #createKeyPair()} method.
 *
 * @return {@code true} if initialization is successful, {@code false} if the lock screen has
 * been disabled or reset after the key was generated, or if a fingerprint got enrolled after
 * the key was generated.
 */
private boolean initSignature() {
    // Create keystore
    try {
        mKeyStore = KeyStore.getInstance("AndroidKeyStore");
    } catch (KeyStoreException e) {
        throw new RuntimeException("Failed to get an instance of KeyStore", e);
    }

    // Create signature
    try {
        mSignature = Signature.getInstance("SHA256withECDSA");
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("Failed to get an instance of Signature", e);
    }


    try {
        mKeyStore.load(null);
        PrivateKey key = (PrivateKey) mKeyStore.getKey(KEY_NAME, null);
        mSignature.initSign(key);
        return true;
    } catch (KeyPermanentlyInvalidatedException e) {
        return false;
    } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
            | NoSuchAlgorithmException | InvalidKeyException e) {
        throw new RuntimeException("Failed to init Cipher", e);
    }
}


private void enroll() {
    try {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        PublicKey publicKey = keyStore.getCertificate(AuthenticateActivity.KEY_NAME).getPublicKey();
        // Provide the public key to the backend. In most cases, the key needs to be transmitted
        // to the backend over the network, for which Key.getEncoded provides a suitable wire
        // format (X.509 DER-encoded). The backend can then create a PublicKey instance from the
        // X.509 encoded form using KeyFactory.generatePublic. This conversion is also currently
        // needed on API Level 23 (Android M) due to a platform bug which prevents the use of
        // Android Keystore public keys when their private keys require user authentication.
        // This conversion creates a new public key which is not backed by Android Keystore and
        // thus is not affected by the bug.
        KeyFactory factory = KeyFactory.getInstance(publicKey.getAlgorithm());
        X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKey.getEncoded());
        PublicKey verificationKey = factory.generatePublic(spec);
        //mStoreBackend.enroll("user", "password", verificationKey);
    } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException |
            IOException | InvalidKeySpecException e) {
        e.printStackTrace();
    }
}

Но функция initSignature() всегда возвращает true.

0 ответов

Другие вопросы по тегам