3

私は Android FingerPrintManagerAPI を使用しており、KeyPairGenerator を使用してキー ペアを作成しています。公開キーでパスワードを暗号化し、fingerPrint を入力してユーザーが認証されたときに復号化したいのですが、プロジェクトを実行するとすぐにクラッシュし、

原因: java.lang.IllegalArgumentException: AndroidKeyStore プロバイダーによってサポートされていない暗号プリミティブ

私はここからコードを使用しました:Android Fingerprint API Encryption and Decryption この投稿は、彼が暗号化と復号化を行うことができ、di が同じコードと手順に従っていることを示しています。ここに私のコードがあります

public KeyStore getKeyStore() {
    try {
        return KeyStore.getInstance("AndroidKeyStore");
    } catch (KeyStoreException exception) {
        throw new RuntimeException("Failed to get an instance of KeyStore", exception);
    }
}

public KeyPairGenerator getKeyPairGenerator() {
    try {
        return KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
    } catch (NoSuchAlgorithmException | NoSuchProviderException exception) {
        throw new RuntimeException("Failed to get an instance of KeyPairGenerator", exception);
    }
}

public Cipher getCipher() {
    try {
        return Cipher.getInstance("RSA");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException exception) {
        throw new RuntimeException("Failed to get an instance of Cipher", exception);
    }
}

private void createKeyPair() {
    try {
        mKeyPairGenerator = getKeyPairGenerator();
        mKeyPairGenerator.initialize(
                new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_DECRYPT)
                        .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
                        .setUserAuthenticationRequired(true)
                        .build());
        mKeyPairGenerator.generateKeyPair();
    } catch (InvalidAlgorithmParameterException exception) {
        throw new RuntimeException(exception);
    }
}

private boolean initCipher(int opmode) {
    try {
        mKeyStore = getKeyStore();
        mKeyStore.load(null);

        mCipher = getCipher();

        if (opmode == Cipher.ENCRYPT_MODE) {

            PublicKey key = mKeyStore.getCertificate(KEY_NAME).getPublicKey();

            PublicKey unrestricted = KeyFactory.getInstance(key.getAlgorithm())
                    .generatePublic(new X509EncodedKeySpec(key.getEncoded()));

            OAEPParameterSpec spec = new OAEPParameterSpec(
                    "SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
            mCipher.init(opmode, unrestricted, spec);
        } else {
            PrivateKey key = (PrivateKey) mKeyStore.getKey(KEY_NAME, null);
            mCipher.init(opmode, key);
        }

        return true;
    } catch (KeyPermanentlyInvalidatedException exception) {
        return false;
    } catch (KeyStoreException | CertificateException | UnrecoverableKeyException
            | IOException | NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException | InvalidAlgorithmParameterException exception) {
        throw new RuntimeException("Failed to initialize Cipher", exception);
    }
}


private void encrypt(String password) {
    try {
        initCipher(Cipher.ENCRYPT_MODE);
        byte[] bytes = mCipher.doFinal(password.getBytes());
        enrcyptedPassword = Base64.encodeToString(bytes, Base64.NO_WRAP);
        Log.d("EncryptedText", enrcyptedPassword);
    } catch (IllegalBlockSizeException | BadPaddingException exception) {
        throw new RuntimeException("Failed to encrypt password", exception);
    }
}

private String decryptPassword(Cipher cipher) {
    try {
        initCipher(Cipher.DECRYPT_MODE);
        byte[] bytes = Base64.decode(enrcyptedPassword, Base64.NO_WRAP);
        return new String(cipher.doFinal(bytes));
    } catch (IllegalBlockSizeException | BadPaddingException | RuntimeException exception) {
        throw new RuntimeException("Failed to decrypt password", exception);
    }
}

ここから、CryptoObject を初期化しています。

createKeyPair();
    if (initCipher(Cipher.ENCRYPT_MODE)) {
        mCryptoObject = new FingerprintManager.CryptoObject
                (mCipher);
        encrypt("1111");
        if (!isFingerprintAuthAvailable()) {
            return;
        }
        mCancellationSignal = new CancellationSignal();
        mSelfCancelled = false;
        mFingerprintManager.authenticate(mCryptoObject, mCancellationSignal, 0 /* flags */, this, null);

この行で例外が発生しています:

mFingerprintManager.authenticate(mCryptoObject, mCancellationSignal, 0 /* flags */, this, null);
4

2 に答える 2

1

暗号化モードでは、Android キーストア キーではないCipher公開キー ( ) を使用してインスタンスを初期化しています。unrestrictedこの問題を解決するには、Android キーストアの公開鍵を使用して初期化します (つまり、 のmKeyStore.getCertificate(KEY_NAME).getPublicKey()代わりにunrestricted)。

ただし、ユーザー認証時に公開鍵暗号化をゲートすることで得られるものは明らかではありません。暗号化は、定義上秘密ではない公開鍵を使用するため、ユーザーが許可することなく、誰でも暗号化操作を実行できます。非対称暗号では、秘密鍵 (定義上、公には知られていない) が関与する唯一の操作は、復号化と署名です。したがって、通常は、復号化またはユーザー認証への署名をゲートするだけで意味があります。

于 2016-06-24T16:31:20.643 に答える