В настоящее время исследуются и разрабатываются различные методы биологической аутентификации, среди которых особенно выделяются методы с использованием информации о лице и голосовых характеристиках. Среди этих методов метод аутентификации по отпечаткам пальцев, используемый для идентификации личности, имеет долгую историю применения, например, для подписи (с помощью отпечатков больших пальцев) и в криминалистике. Применение аутентификации по отпечаткам пальцев также получило развитие в нескольких областях компьютерного мира, и в последние годы эти методы стали широко признанной удобной технологией (например, простота ввода), используемой в некоторых областях, таких как идентификация владельца интеллектуального мобильного телефона (в основном используется для разблокировки экрана).
На фоне этих тенденций Android 6.0 (API Level 23) интегрировал на терминалах структуру аутентификации по отпечаткам пальцев, позволяя приложениям использовать функцию аутентификации по отпечаткам пальцев для идентификации личности. В следующем разделе мы обсудим некоторые меры безопасности, которые следует учитывать при использовании аутентификации по отпечаткам пальцев.
Ниже мы предоставляем пример кода, который позволяет приложениям использовать функцию аутентификации по отпечаткам пальцев Android.
Основные моменты:
MainActivity.java
package authentication.fingerprint.android.jssec.org.fingerprintauthentication;
import android.app.AlertDialog;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
public class MainActivity extends AppCompatActivity {
private FingerprintAuthentication mFingerprintAuthentication;
private static final String SENSITIVE_DATA = "sensitive data";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFingerprintAuthentication = new FingerprintAuthentication(this);
Button button_fingerprint_auth = (Button) findViewById(R.text.button_fingerprint_auth);
button_fingerprint_auth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mFingerprintAuthentication.isAuthenticating()) {
if (authenticateByFingerprint()) {
showEncryptedData(null);
setAuthenticationState(true);
}
} else {
mFingerprintAuthentication.cancel();
}
}
});
}
private boolean authenticateByFingerprint() {
if (!mFingerprintAuthentication.isFingerprintHardwareDetected()) {
// Terminal is not equipped with a fingerprint sensor
return false;
}
if (!mFingerprintAuthentication.isFingerprintAuthAvailable()) {
// *** POINT 3 *** Notify users that fingerprint registration will be required to create a key
new AlertDialog.Builder(this)
.setTitle(R.string.app_name)
.setMessage("No fingerprint information has been registered.¥n" +
"Click ¥"Security¥" on the Settings menu to register fingerprints. ¥n" +
"Registering fingerprints allows easy authentication.")
.setPositiveButton("OK", null)
.show();
return false;
}
// Callback that receives the results of fingerprint authentication
FingerprintManager.AuthenticationCallback callback = new FingerprintManager.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
showMessage(errString, R.color.colorError);
reset();
}
@Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
showMessage(helpString, R.color.colorHelp);
}
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
Cipher cipher = result.getCryptoObject().getCipher();
try {
// *** POINT 7*** Restrict encrypted data to items that can be restored (replaced) by methods other than fingerprint authentication
byte[]
Примечание: в тексте запроса присутствуют фрагменты кода на языке Java. Они были переведены на русский язык. Вот перевод текста на русский язык:
encrypted = cipher.doFinal(SENSITIVE_DATA.getBytes());
showEncryptedData(encrypted);
} catch (IllegalBlockSizeException | BadPaddingException e) {
}
showMessage(getString(R.string.fingerprint_auth_succeeded), R.color.colorAuthenticated);
reset();
}
@Override
public void onAuthenticationFailed() {
showMessage(getString(R.string.fingerprint_auth_failed), R.color.colorError);
}
};
if (mFingerprintAuthentication.startAuthentication(callback)) {
showMessage(getString(R.string.fingerprint_processing), R.color.colorNormal);
return true;
}
return false;
}
private void setAuthenticationState(boolean authenticating) {
Button button = (Button) findViewById(R.id.button_fingerprint_auth);
button.setText(authenticating ? R.string.cancel : R.string.authenticate);
}
private void showEncryptedData(byte[] encrypted) {
TextView textView = (TextView) findViewById(R.id.encryptedData);
if (encrypted != null) {
textView.setText(Base64.encodeToString(encrypted, 0));
} else {
textView.setText("");
}
}
private String getCurrentTimeString() {
long currentTimeMillis = System.currentTimeMillis();
Date date = new Date(currentTimeMillis);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
return simpleDateFormat.format(date);
}
private void showMessage(CharSequence msg, int colorId) {
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(getCurrentTimeString() + " :¥n" + msg);
textView.setTextColor(getResources().getColor(colorId, null));
}
private void reset() {
setAuthenticationState(false);
}
FingerprintAuthentication.java
package authentication.fingerprint.android.jssec.org.fingerprintauthentication;
import android.app.KeyguardManager;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.os.CancellationSignal;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyInfo;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
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 java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
public class FingerprintAuthentication {
private static final String KEY_NAME = "KeyForFingerprintAuthentication";
private static final String PROVIDER_NAME = "AndroidKeyStore";
private KeyguardManager mKeyguardManager;
private FingerprintManager mFingerprintManager;
private CancellationSignal mCancellationSignal;
private KeyStore mKeyStore;
private KeyGenerator mKeyGenerator;
private Cipher mCipher;
public FingerprintAuthentication(Context context) {
mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
mFingerprintManager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE
);
reset();
}
public boolean startAuthentication(final FingerprintManager.AuthenticationCallback callback) {
if (!generateAndStoreKey())
return false;
if (!initializeCipherObject())
return false;
FingerprintManager.CryptoObject cryptoObject = new
``` ```
new RuntimeException("failed to generate a key", e);
}
}
private boolean initializeCipherObject() {
try {
mKeyStore.load(null);
SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null);
SecretKeyFactory factory = SecretKeyFactory.getInstance(KeyProperties.KEY_ALGORITHM_AES, PROVIDER_NAME);
KeyInfo info = (KeyInfo) factory.getKeySpec(key, KeyInfo.class);
mCipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
// *** POINT 6 *** Design your app on the assumption that the status of fingerprint registration will change between when keys are created and when keys are used
return false;
} catch (KeyStoreException | CertificateException
| UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeySpecException
| NoSuchProviderException | InvalidKeyException e) {
throw new RuntimeException("failed to init Cipher", e);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="authentication.fingerprint.android.jssec.org.fingerprintauthentication" >
<!-- +++ POINT 1 *** Declare the use of the USE_FINGERPRINT permission -->
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
При использовании аутентификации по отпечатку пальца необходимо соблюдать следующие правила:
При создании ключа с помощью функции аутентификации по отпечаткам пальцев необходимо использовать надёжный алгоритм шифрования, который соответствует определённым стандартам, чтобы предотвратить перехват данных третьими лицами. Фактически, выбор безопасного и надёжного алгоритма применим не только к алгоритмам шифрования, но также к режимам шифрования и заполнению.
Для получения дополнительной информации о выборе алгоритма см. раздел «5.6.2.2 Использование сильного алгоритма (особенно алгоритма, соответствующего соответствующим стандартам) (обязательно)».
Когда приложение использует функцию аутентификации по отпечаткам пальцев для шифрования данных в приложении, дизайн приложения должен позволять восстанавливать (заменять) данные без использования аутентификации по отпечаткам пальцев. В целом, использование биометрической информации может привести к различным проблемам, включая конфиденциальность, сложность модификации и ошибки распознавания, поэтому лучше избегать полагаться исключительно на биометрическую информацию для аутентификации.
Например, если данные в приложении зашифрованы с помощью ключа, созданного с помощью функции аутентификации по отпечаткам пальцев, а ключ хранится в терминале, и пользователь впоследствии удаляет данные отпечатков пальцев, то ключ становится недоступным и его невозможно скопировать. Если данные не могут быть восстановлены без аутентификации по отпечаткам пальцев, существует значительный риск того, что данные станут непригодными для использования.
Кроме того, удаление биометрических данных не является единственным случаем, когда ключ, созданный с помощью функции аутентификации по отпечаткам пальцев, может стать недоступным. На Nexus 5X, например, если ключ создан с помощью функции аутентификации по отпечаткам пальцев и затем зарегистрирован как дополнительная биометрическая информация, ранее созданный ключ становится недоступен [30]. Также нельзя исключать возможность того, что ключ станет недоступным из-за ошибок распознавания датчика отпечатков пальцев, которые обычно позволяют правильно использовать ключ.
[30] Информация взята из версии от 1 сентября 2016 года. Это может быть изменено в будущем.
Чтобы создать ключ с помощью функции аутентификации по отпечаткам пальцев, необходимо зарегистрировать отпечатки пальцев пользователя на терминале. Разработчики должны помнить, что отпечатки пальцев представляют собой важные личные данные, и стремиться объяснить пользователям, почему использование данных отпечатков пальцев является необходимым или удобным.
Уведомление пользователей о необходимости регистрации отпечатков пальцев
if (!mFingerprintAuthentication.isFingerprintAuthAvailable()) {
// **Point** Notify users that fingerprint registration will be required to create a key
new AlertDialog.Builder(this)
.setTitle(R.string.app_name)
.setMessage("No fingerprint information has been registered.¥n" +
" Click ¥"Security¥" on the Settings menu to register fingerprints.¥n" +
" Registering fingerprints allows easy authentication.")
.setPositiveButton("OK", null)
.show();
return false;
}
Чтобы приложение могло использовать функцию аутентификации по отпечаткам пальцев, должны выполняться два условия.
Регистрация отпечатков пальцев пользователя
Информация об отпечатках пальцев может быть зарегистрирована только через меню настроек «Безопасность»; обычно приложение не может выполнить процесс регистрации отпечатков пальцев. Поэтому, если приложение пытается использовать функцию аутентификации по отпечаткам пальцев без зарегистрированных отпечатков пальцев, приложение должно направить пользователя в меню настроек и побудить его зарегистрировать свои отпечатки пальцев. В этом случае приложение должно предоставить пользователю некоторые объяснения, объясняющие, почему использование информации об отпечатках пальцев является необходимым и удобным.
Также, в качестве предварительного условия для регистрации отпечатков пальцев, терминал должен иметь альтернативный механизм блокировки экрана. Если блокировка экрана отключена после регистрации отпечатков пальцев в терминале, зарегистрированная информация об отпечатках пальцев будет удалена.
Создание и регистрация ключа
Чтобы связать ключ с зарегистрированными отпечатками пальцев, используйте экземпляр KeyStore
поставщика AndroidKeyStore
, чтобы создать и зарегистрировать новый ключ или зарегистрировать существующий ключ. Чтобы создать ключ, связанный с информацией об отпечатках пальцев, настройте параметры при создании KeyGenerator
, чтобы включить запрос аутентификации пользователя.
Создание и регистрация связанного с отпечатками пальцев ключа
try {
// Obtain an instance from the "AndroidKeyStore" Provider
KeyGenerator keyGenerator =
``` Чтобы связать информацию об отпечатках пальцев и существующий ключ, используйте элемент KeyStore для регистрации этого ключа в уже настроенных элементах, чтобы активировать запросы аутентификации пользователя.
Связывание информации об отпечатках пальцев с существующим ключом:
```java
SecretKey key = …; // существующий ключ
KeyStore keyStore = KeyStore.getInstance(«AndroidKeyStore»);
keyStore.load(null);
keyStore.setEntry(
"alias_for_the_key",
new KeyStore.SecretKeyEntry(key),
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
.setUserAuthenticationRequired(true) // Включить запросы на аутентификацию пользователя (отпечаток пальца)
.build());
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )