在应用程序中使用签名实现指纹认证
Posted
技术标签:
【中文标题】在应用程序中使用签名实现指纹认证【英文标题】:Implemented Finger Print Authentication in Application with signature 【发布时间】:2018-10-28 19:45:28 【问题描述】:在 android 6.0 以下运行应用程序时遇到问题
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
if (!fingerprintManager.isHardwareDetected())
/**
* An error message will be displayed if the device does not contain the fin.gerprint hardware.
* However if you plan to implement a default authentication method,
* you can redirect the user to a default authentication ctivity from here.
* Example:
*
*/
else
// Checks whether fingerprint permission is set on manifest
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED)
// permission not granted
else
// Check whether at least one fingerprint is registered
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
// Checks whether lock screen security is enabled or not
if (!keyguardManager.isKeyguardSecure())
// finger print not support
else
if (!fingerprintManager.hasEnrolledFingerprints())
// finger print not enrolled
else
/*Amit Verma EC signature*/
createKeyPair();
if (initSignature())
ConstantDeclaration.mCryptoObject = new FingerprintManager.CryptoObject(mSignature);
这是生成密钥对的代码
@TargetApi(Build.VERSION_CODES.M)
private void createKeyPair()
// 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
KeyPairGenerator mKeyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
mKeyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_SIGN)
.setDigests(KeyProperties.DIGEST_SHA1)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
// Require the user to authenticate with a fingerprint to authorize
// every use of the private key
// .setUserAuthenticationRequired(true)
.setUserAuthenticationRequired(false)
.build());
mKeyPairGenerator.generateKeyPair();
catch (InvalidAlgorithmParameterException e)
throw new RuntimeException(e);
catch (NoSuchAlgorithmException e)
e.printStackTrace();
catch (NoSuchProviderException e)
e.printStackTrace();
这里是签名启动的代码。
@TargetApi(Build.VERSION_CODES.M)
private boolean initSignature()
try
mKeyStore = KeyStore.getInstance("AndroidKeyStore");
mKeyStore.load(null);
PrivateKey key = (PrivateKey) mKeyStore.getKey(KEY_NAME, null);
// String strKey = Base64.encodeToString(key.getEncoded(),Base64.DEFAULT);
// System.out.println("PrivateKey::"+strKey);
mSignature = Signature.getInstance("SHA1withECDSA");
mSignature.initSign(key);
PublicKey publicKey = mKeyStore.getCertificate(KEY_NAME).getPublicKey();
String strPublicKey = Base64.encodeToString(publicKey.getEncoded(), Base64.DEFAULT);
Singleton.getInstance().public_key_fp = strPublicKey;
return true;
catch (KeyPermanentlyInvalidatedException e)
return false;
catch (Exception e)
throw new RuntimeException("Failed to init Cipher", e);
/*catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeyException e)
throw new RuntimeException("Failed to init Cipher", e);
*/
此代码运行良好,但是当我在 Android 6.0 以下运行我的应用程序时,启动应用程序时出现异常。
Android version: 19
Device: samsung SM-J100ML
App version: 7
Line Number1: java.lang.Class.newInstanceImpl(Native Method)
Description : java.lang.VerifyError: launcherActivity
at java.lang.Class.newInstanceImpl(Native Method)
at java.lang.Class.newInstance(Class.java:1208)
at android.app.Instrumentation.newActivity(Instrumentation.java:1068)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2493)
at android.app.ActivityThread.access$800(ActivityThread.java:166)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1283)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5584)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
at dalvik.system.NativeStart.main(Native Method)
我认为签名导入的问题是 import java.security.Signature;
【问题讨论】:
我的猜测是您声明了某些字段或覆盖了 API 级别 19 上不存在的某些方法。java.security.Signature
自 API 级别 1 以来一直存在:developer.android.com/reference/java/security/Signature 这不是您的问题。
Signature
本身不应导致VerifyError
。但是删除Signature
会强制你删除使用Signature
的其他代码,并且可能该代码是VerifyError
的来源。
诀窍是阅读 logcat..在异常/崩溃发生之前你会发现 class not found 行(崩溃上方的 5-10 行)
尝试删除 KeyPermanentlyInvalidatedException 并在 catch 中只保留 Exception 类
【参考方案1】:
我通过阅读上面评论中所说的 logcat 发现了问题,
Could not find class 'android.security.keystore.KeyGenParameterSpec$Builder'
和
Could not find class 'android.hardware.fingerprint.FingerprintManager'
我用谷歌搜索了上面的课程,找到了这个链接here
所以我删除 catch 块 InvalidAlgorithmParameterException
,**KeyPermanentlyInvalidatedException**
并替换为 仅父类“异常”。
【讨论】:
就像我在上面猜到的那样,它可以工作:) 呵呵... KeyPermanentlyInvalidatedException 被添加到developer.android.com/reference/android/security/keystore/… 中提到的 API 23 中以上是关于在应用程序中使用签名实现指纹认证的主要内容,如果未能解决你的问题,请参考以下文章
微信小程序 使用HMACSHA1和md5为登陆注册报文添加指纹验证签名
Google Play 签名 SHA256 指纹发布一次后会改变吗?