【问题标题】:Android Fingerprint API and Private/Public keysAndroid 指纹 API 和私钥/公钥
【发布时间】:2017-03-07 16:42:07
【问题描述】:

当我首先注册指纹并生成KeyPair 时,PrivateKey 在我第二次使用时会失效。这种情况只发生一次。只有我一个人有这个问题吗?我的代码有问题吗?

我无法使用任何其他密钥,因为我正在使用 PrivateKey 对数据进行签名。

步骤:

  1. 擦除所有指纹
  2. 登记一个指纹
  3. 生成KeyPair 并使用FingerprintManager :: authenticate
  4. 在下次使用FingerprintManager :: authenticate PrivateKey 时永久失效。这只是第一次发生

在我生成KeyPair的代码下方

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keystore.load(null);
KeyPairGenerator generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
generator.initialize(new KeyGenParameterSpec.Builder("key_name", KeyProperties.PURPOSE_SIGN)
    .setDigests(digest) // I have defined digest before
    .setSignaturePaddings(paddings) // I have defined paddings before
    .setUserAuthenticationRequired(true)
    .build());
generator.generateKeyPair();

这是我为数据签名调用指纹认证的代码:

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
Signature signature = Signature.getInstance("signing_algorithm");
PrivateKey privateKey = (PrivateKey) keyStore.getKey("key_name", null);
signature.initSign(privateKey); // Here I get KeyPermanentlyInvalidatedException
CryptoObject crypto = new CryptoObject(signature);
FingerprintManager fingerprintManager = context.getSystemService(FingerprintManager.class);
CancellationSignal cancellationSignal = new CancellationSignal();
AuthenticationCallback authenticationCallback = new AuthenticationCallback() {
    ...
};
fingerprintManager.authenticate(crypto, cancelationSignal, 0, authenticationCallback, null);

【问题讨论】:

  • 在我看来,您正在尝试重复使用在擦除指纹数据之前设置的密钥。确保在擦除指纹后重新设置密钥。您可以尝试将 setInvalidatedByBiometricEnrollment 设置为 false 看看会发生什么,
  • 一开始我会擦指纹,然后只注册一个,生成密钥。当我第一次使用生成的密钥时,一切都按预期工作,但是当我使用指纹进行身份验证以第二次使用密钥时,它会失效。我确实尝试将 setInvalidateByBiometricEnrollment 设置为 false 并有所帮助,但这并不安全。
  • 那么在我看来这是phonentoure使用的问题,制造商使用的指纹软件中的一个错误,你在所有制造商的手机上得到相同的结果吗?
  • 我还希望您使用密钥,而不是私钥。 :)
  • 最后,如果我的记忆没有出卖我,为了注册或更改指纹,用户必须进行身份验证。所以是的,允许生物识别注册不太安全,但并非不安全。如果另一种方法是在您收到异常时重新生成您的密钥(看起来如此),那么我更愿意允许注册,因为密钥失效还有其他原因,例如用户从安全密钥保护中更改。如果普通屏幕锁定对于您的用例来说足够安全(请咨询进行安全分析的人员),这可能是您的替代方案。

标签: android private-key fingerprint


【解决方案1】:

你可以在 github 上看到这个:希望对你有帮助:Confirm Credentials

【讨论】:

    【解决方案2】:

    我试试这个link 并完美地工作。

    首先你需要设置Minimum sdk look like the Picture

    Mainfest 中的第二组权限

       <uses-permission android:name="android.permission.USE_FINGERPRINT" />
    

    第三

    generateKey() 函数生成加密密钥,然后安全地存储在设备上。

    cipherInit() 函数初始化将用于创建加密指纹管理器的密码。

    CryptoObject 实例和其他各种检查在启动验证过程之前在 onCreate() 方法中实现。

    FingerPrintActivty.java

    import android.Manifest;
    import android.annotation.TargetApi;
    import android.app.KeyguardManager;
    import android.content.pm.PackageManager;
    import android.hardware.fingerprint.FingerprintManager;
    import android.os.Build;
    import android.security.keystore.KeyGenParameterSpec;
    import android.security.keystore.KeyPermanentlyInvalidatedException;
    import android.security.keystore.KeyProperties;
    import android.support.v4.app.ActivityCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.TextView;
    import java.io.IOException;
    import java.security.InvalidAlgorithmParameterException;
    import java.security.InvalidKeyException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.CertificateException;
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
     
     
    public class FingerprintActivity extends AppCompatActivity {
     
     
       private KeyStore keyStore;
       // Variable used for storing the key in the Android Keystore container
       private static final String KEY_NAME = "androidHive";
       private Cipher cipher;
       private TextView textView;
     
     
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_fingerprint);
     
     
           // Initializing both Android Keyguard Manager and Fingerprint Manager
           KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
           FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
     
     
           textView = (TextView) findViewById(R.id.errorText);
     
     
           // Check whether the device has a Fingerprint sensor.
           if(!fingerprintManager.isHardwareDetected()){
               /**
                * An error message will be displayed if the device does not contain the fingerprint hardware.
                * However if you plan to implement a default authentication method,
                * you can redirect the user to a default authentication activity from here.
                * Example:
                * Intent intent = new Intent(this, DefaultAuthenticationActivity.class);
                * startActivity(intent);
                */
               textView.setText("Your Device does not have a Fingerprint Sensor");
           }else {
               // Checks whether fingerprint permission is set on manifest
               if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
                   textView.setText("Fingerprint authentication permission not enabled");
               }else{
                   // Check whether at least one fingerprint is registered
                   if (!fingerprintManager.hasEnrolledFingerprints()) {
                       textView.setText("Register at least one fingerprint in Settings");
                   }else{
                       // Checks whether lock screen security is enabled or not
                       if (!keyguardManager.isKeyguardSecure()) {
                           textView.setText("Lock screen security not enabled in Settings");
                       }else{
                           generateKey();
     
     
                           if (cipherInit()) {
                               FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
                               FingerprintHandler helper = new FingerprintHandler(this);
                               helper.startAuth(fingerprintManager, cryptoObject);
                           }
                       }
                   }
               }
           }
       }
     
     
       @TargetApi(Build.VERSION_CODES.M)
       protected void generateKey() {
           try {
               keyStore = KeyStore.getInstance("AndroidKeyStore");
           } catch (Exception e) {
               e.printStackTrace();
           }
     
     
           KeyGenerator keyGenerator;
           try {
               keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
           } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
               throw new RuntimeException("Failed to get KeyGenerator instance", e);
           }
     
     
           try {
               keyStore.load(null);
               keyGenerator.init(new
                       KeyGenParameterSpec.Builder(KEY_NAME,
                       KeyProperties.PURPOSE_ENCRYPT |
                               KeyProperties.PURPOSE_DECRYPT)
                       .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                       .setUserAuthenticationRequired(true)
                       .setEncryptionPaddings(
                               KeyProperties.ENCRYPTION_PADDING_PKCS7)
                       .build());
               keyGenerator.generateKey();
           } catch (NoSuchAlgorithmException |
                   InvalidAlgorithmParameterException
                   | CertificateException | IOException e) {
               throw new RuntimeException(e);
           }
       }
     
     
       @TargetApi(Build.VERSION_CODES.M)
       public boolean cipherInit() {
           try {
               cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
           } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
               throw new RuntimeException("Failed to get Cipher", e);
           }
     
     
           try {
               keyStore.load(null);
               SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
                       null);
               cipher.init(Cipher.ENCRYPT_MODE, key);
               return true;
           } catch (KeyPermanentlyInvalidatedException e) {
               return false;
           } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
               throw new RuntimeException("Failed to init Cipher", e);
           }
       }
    }
    

    FingerprintAuthenticationHandler.Class

    import android.Manifest;
    import android.app.Activity;
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.hardware.fingerprint.FingerprintManager;
    import android.os.CancellationSignal;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.widget.TextView;
     
     
    /**
    * Created by whit3hawks on 11/16/16.
    */
    public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
     
     
       private Context context;
     
     
       // Constructor
       public FingerprintHandler(Context mContext) {
           context = mContext;
       }
     
     
       public void startAuth(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) {
           CancellationSignal cancellationSignal = new CancellationSignal();
           if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
               return;
           }
           manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
       }
     
     
       @Override
       public void onAuthenticationError(int errMsgId, CharSequence errString) {
           this.update("Fingerprint Authentication error\n" + errString, false);
       }
     
     
       @Override
       public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
           this.update("Fingerprint Authentication help\n" + helpString, false);
       }
     
     
       @Override
       public void onAuthenticationFailed() {
           this.update("Fingerprint Authentication failed.", false);
       }
     
     
       @Override
       public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
           this.update("Fingerprint Authentication succeeded.", true);
       }
     
     
       public void update(String e, Boolean success){
           TextView textView = (TextView) ((Activity)context).findViewById(R.id.errorText);
           textView.setText(e);
           if(success){
               textView.setTextColor(ContextCompat.getColor(context,R.color.colorPrimaryDark));
           }
       }
    }
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2013-07-09
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      • 1970-01-01
      • 2016-03-27
      • 2016-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多