美文网首页鱼乐Android研究院项目
新的安卓样本: 指纹认证API

新的安卓样本: 指纹认证API

作者: 程序猿老王 | 来源:发表于2016-01-13 00:38 被阅读4976次
    指纹识别

    Android 6.0棉花糖 在几个月前就已向用户公开提供。一路走来,我们一直在更新我们的代码示例集合,希望可以着重介绍一些让您兴奋的新功能。

    我们将发布 AsymmetricFingerprintDialog,这是一个新示例,演示如何在一个客户端或者服务器环境中安全地集成兼容的指纹读取器(如 Nexus Imprint)。

    让我们详细了解一下此示例的工作方式,探讨它如何成为此前在公众预览版期间发布的 FingerprintDialog示例的有益补充。


    对称密钥与非对称密钥

    Android Fingerprint API 通过谨慎地保留设备上安全硬件中包含的用户指纹特征来保护用户隐私。这可以防范恶意的入侵者,确保用户即使在不受信任的应用中也可以安全地使用他们的指纹。

    Android 还可以为应用程序开发者提供保护,确保在正确识别用户指纹之后才授予用户对安全数据或资源的访问权限。这可防止篡改应用,从而为离线数据和在线交互提供加密级别的安全性。

    当用户激活他们的指纹读取器时,实际上他们是在解锁一个由硬件支持的加密保险库。作为开发者,您可以根据应用程序的需求来选择在该保险库中存储哪些类型的关键资料:

    对称密钥:与密码相似,对称密钥允许对本地数据进行加密。它非常适合用于保护对数据库或离线文件的访问。
    非对称密钥:提供一个由公钥和私钥组成的密钥对。公钥可以通过互联网安全地发送并存储在远程服务器上。稍后,可使用私钥对数据进行签名,以便能够通过公钥验证签名。已签名的数据无法被篡改,可以确定地标识数据的原始作者。通过此方式,非对称密钥可用于网络登录和验证在线交易。类似地,也可使用公钥加密数据,以便该数据只能通过私钥解密。

    此示例演示了如何使用非对称密钥对网上购物进行身份验证。如果您想了解如何使用对称密钥,请查看之前发布的 FingerprintDialog 示例。

    下面形象地解释了如何使用对称密钥流程将 Android 应用、用户及后端完美地结合在一起:

    新的安卓样本: 指纹认证API

    设置:创建一个非对称密钥对

    首先,您需要创建一个非对称密钥对,如下所示

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

    请注意,.setUserAuthenticationRequired(true) 需要此用户使用注册的指纹进行身份验证,以授权私钥的每次使用。

    然后,您可以检索已创建的私钥和公钥,如下所示

    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);
    PublicKey publicKey =
       keyStore.getCertificate(MainActivity.KEY_NAME).getPublicKey();

    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);
    PrivateKey key = (PrivateKey) keyStore.getKey(KEY_NAME, null);

    注册:向服务器注册公钥

    其次,您需要将公钥传输到后端,以便将来后端可以验证由该用户授权(即通过与此公钥对应的私钥进行签名)的交易。此示例使用伪后端实现,仅供参考,因此,它模拟公钥的传输,但在现实中,您需要通过网络传输此公钥。

    boolean enroll(String userId, String password, PublicKey publicKey);

    让我们开始吧:使用指纹签署交易

    为让该用户能够验证交易(例如,购买某件商品),请提示用户触摸指纹传感器。

    新的安卓样本: 指纹认证API

    然后,开始侦听指纹,如下所示:

    Signature.getInstance("SHA256withECDSA");
    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);
    PrivateKey key = (PrivateKey) keyStore.getKey(KEY_NAME, null);
    signature.initSign(key);
    CryptoObject cryptObject = new FingerprintManager.CryptoObject(signature);

    CancellationSignal cancellationSignal = new CancellationSignal();
    FingerprintManager fingerprintManager =
       context.getSystemService(FingerprintManager.class);
    fingerprintManager.authenticate(cryptoObject, cancellationSignal, 0, this, null);

    完成:将此数据发送到后端并进行验证

    在身份验证成功后,发送已签名的数据(在此示例中为购买交易的商品清单)发送到后端,如下所示:

    Signature signature = cryptoObject.getSignature();
    // Include a client nonce in the transaction so that the nonce is also signed
    // by the private key and the backend can verify that the same nonce can't be used
    // to prevent replay attacks.
    Transaction transaction = new Transaction("user", 1, new SecureRandom().nextLong());
    try {
     signature.update(transaction.toByteArray());
     byte[] sigBytes = signature.sign();
     // Send the transaction and signedTransaction to the dummy backend
     if (mStoreBackend.verify(transaction, sigBytes)) {
       mActivity.onPurchased(sigBytes);
       dismiss();
     } else {
       mActivity.onPurchaseFailed();
       dismiss();
     }
    } catch (SignatureException e) {
     throw new RuntimeException(e);
    }

    最后,使用在第 2 步中注册的公钥在后端验证已签名的数据。

    @Override
    public boolean verify(Transaction transaction, byte[] transactionSignature) {
     try {
       if (mReceivedTransactions.contains(transaction)) {
         // It verifies the equality of the transaction including the client nonce
         // So attackers can't do replay attacks.
         return false;
       }
       mReceivedTransactions.add(transaction);
       PublicKey publicKey = mPublicKeys.get(transaction.getUserId());
       Signature verificationFunction = Signature.getInstance("SHA256withECDSA");
       verificationFunction.initVerify(publicKey);
       verificationFunction.update(transaction.toByteArray());
       if (verificationFunction.verify(transactionSignature)) {
         // Transaction is verified with the public key associated with the user
         // Do some post purchase processing in the server
         return true;
       }
     } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
       // In a real world, better to send some error message to the user
     }
     return false;
    }

    此时,您可以假设该用户已正确使用其指纹通过身份验证,因为,如第 1 步所述,每次使用私钥之前均需要对用户进行身份验证。现在开始在后端进行后处理,并通知用户交易成功!

    其他更新的示例

    我们还针对 Android For Work API 提供了几个与 Android 6.0棉花糖 相关的更新,供您研读:

    AppRestrictionEnforcer 和 AppRestrictionSchema 这些示例最初是在推出应用限制功能(作为 Android for Work API 的一部分)时在 Android 5.0 棒棒糖中发布的。AppRestrictionEnforcer 演示作为配置文件所有者如何对其他应用设置限制。AppRestrictionSchema 定义了一些可以由 AppRestrictionEnforcer 控制的限制。此更新显示如何使用 Android 6.0 中引入的 2 个额外的限制类型。

    原文来自【安卓开发者全球博客】:

    android-developers.blogspot.com/

    相关文章

      网友评论

      • JamieHe嘉:您好,有个问题想请教下。这个keystore生成的公私钥对,私钥是放在se里面的吗?还是软的方式?
      • dc400f4c0b1c:请问能说下指纹识别的非对称秘钥下的用户登录过程吗,打扰了
      • 叶落非秋:请问一下,想利用android设备上的指纹识别模块实现签到功能,可以实现吗?
        我现在是这么想的,当读取到用户指纹时,不和本地用户解锁手机的那个指纹对比而是和远程服务器用户事先录好的指纹进行对比。
        叶落非秋:@紫米初心 不可以,Android的指纹信息是拿不到的,Android设备只允许和手机上已经录入的指纹进行匹配,你只能得到匹配成功或者失败的结果!
        紫米初心:你好,我也是这样想的,不过是想在微信小程序上实现签到,不知道您先在解决问题了吗?想借鉴一下您的思路,是怎么读取用户指纹的?
      • 曾樑:这个和三星的那个支付是两个东西对吧
        程序猿老王:@曾樑 这个就是Android6.0的指纹识别api,nexus6手机上已经有指纹识别了,可以买个玩玩😜

      本文标题:新的安卓样本: 指纹认证API

      本文链接:https://www.haomeiwen.com/subject/nzjckttx.html