我正在尝试使用Signature对象使用指纹认证来签署和验证数据。它可以很好地用于签名,但是在进行验证时出现此错误:


  java.lang.IllegalArgumentException:不支持的加密基元
  AndroidKeyStore提供程序:签名对象:
  SHA256withECDSA,spi:
  com.android.org.conscrypt.OpenSSLSignature$SHA256ECDSA@cf4a416


不是在生成密钥时抛出异常(此部分很好),而是在调用fingerprintManager.authenticate(cryptoObject, ...)时抛出

基本上这就是我生成CryptoObject实例的方式:

KeyPairGenerator signatureKeyGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
signatureKeyGenerator.initialize(new KeyGenParameterSpec.Builder(keyName, KeyProperties.PURPOSE_SIGN)
        .setDigests(KeyProperties.DIGEST_SHA256)
        .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
        .setUserAuthenticationRequired(true)
        .build());

KeyPair signatureKey = signatureKeyGenerator.generateKeyPair();

Signature signature = Signature.getInstance("SHA256withECDSA");

switch (MODE) {
    case KeyProperties.PURPOSE_SIGN:
        signature.initSign(signatureKey.getPrivate());
        break;
    case KeyProperties.PURPOSE_VERIFY:
        KeyFactory factory = KeyFactory.getInstance(signatureKey.getPublic().getAlgorithm());
        X509EncodedKeySpec spec = new X509EncodedKeySpec(signatureKey.getPublic().getEncoded());
        PublicKey unrestrictedPublicKey = factory.generatePublic(spec);
        signature.initVerify(unrestrictedPublicKey);
        break;
}

CryptoObject cryptoObject new CryptoObject(signature);


我尝试将| KeyProperties.PURPOSE_VERIFY添加到KeyGenParameterSpec.Builder,但是也没有用,无论如何,这就是他们在Google官方仓库中进行的操作:https://github.com/googlesamples/android-AsymmetricFingerprintDialog(很奇怪...)

最后,我尝试研究Android源代码,以了解引发异常的原因:AndroidKeyStoreProvider.java

Object spi = ((Signature) cryptoPrimitive).getCurrentSpi();
if (spi == null) {
    throw new IllegalStateException("Crypto primitive not initialized");
} else if (!(spi instanceof KeyStoreCryptoOperation)) {
    throw new IllegalArgumentException(
            "Crypto primitive not backed by AndroidKeyStore provider: " + cryptoPrimitive
            + ", spi: " + spi);
}


但是我什至找不到getCurrentSpi()方法...

任何帮助将不胜感激 !

最佳答案

在验证模式下,您正在使用不是Android Keystore密钥的公共密钥来初始化Signature实例。您的问题类似于Initializing FingerpringManager.Crypto Object, getting Crypto primitive not backed by AndroidKeyStore provider?

验证数字签名不是限制性操作,因为它已被公钥所填充,因此您实际上不需要FingerprintManager和CryptoObject

因此,您可以直接使用

   signature.verify(sigToVerify)`


或使用Android Keystore公钥初始化Signature对象

  signature.initVerify(signatureKey.getPublic())

09-12 04:03