1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-android-app-sec-guidebook

Клонировать/Скачать
5.7.md 24 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 27.11.2024 20:24 c13bfb7

5.7 Использование функции аутентификации по отпечатку пальца

В настоящее время исследуются и разрабатываются различные методы биологической аутентификации, среди которых особенно выделяются методы с использованием информации о лице и голосовых характеристиках. Среди этих методов метод аутентификации по отпечаткам пальцев, используемый для идентификации личности, имеет долгую историю применения, например, для подписи (с помощью отпечатков больших пальцев) и в криминалистике. Применение аутентификации по отпечаткам пальцев также получило развитие в нескольких областях компьютерного мира, и в последние годы эти методы стали широко признанной удобной технологией (например, простота ввода), используемой в некоторых областях, таких как идентификация владельца интеллектуального мобильного телефона (в основном используется для разблокировки экрана).

На фоне этих тенденций Android 6.0 (API Level 23) интегрировал на терминалах структуру аутентификации по отпечаткам пальцев, позволяя приложениям использовать функцию аутентификации по отпечаткам пальцев для идентификации личности. В следующем разделе мы обсудим некоторые меры безопасности, которые следует учитывать при использовании аутентификации по отпечаткам пальцев.

5.7.1 Пример кода

Ниже мы предоставляем пример кода, который позволяет приложениям использовать функцию аутентификации по отпечаткам пальцев Android.

Основные моменты:

  1. Объявить использование разрешения USE_FINGERPRINT.
  2. Получить экземпляр от поставщика AndroidKeyStore.
  3. Сообщить пользователю, что для создания ключа требуется регистрация отпечатка пальца.
  4. При создании (регистрации) ключа используйте надёжный алгоритм шифрования (соответствующий стандарту).
  5. При создании (регистрации) ключа включите запрос аутентификации пользователя (не указывайте продолжительность включения аутентификации).
  6. Предпосылкой разработки вашего приложения является то, что состояние регистрации отпечатка пальца будет меняться во время создания и использования ключа.
  7. Ограничьте зашифрованные данные вещами, которые можно восстановить (заменить) другими способами, кроме аутентификации по отпечаткам пальцев.

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.7.2 Правила использования

При использовании аутентификации по отпечатку пальца необходимо соблюдать следующие правила:

5.7.2.1 Создание (регистрация) ключа должно осуществляться с использованием надёжного алгоритма шифрования (обязательно)

При создании ключа с помощью функции аутентификации по отпечаткам пальцев необходимо использовать надёжный алгоритм шифрования, который соответствует определённым стандартам, чтобы предотвратить перехват данных третьими лицами. Фактически, выбор безопасного и надёжного алгоритма применим не только к алгоритмам шифрования, но также к режимам шифрования и заполнению.

Для получения дополнительной информации о выборе алгоритма см. раздел «5.6.2.2 Использование сильного алгоритма (особенно алгоритма, соответствующего соответствующим стандартам) (обязательно)».

5.7.2.2 Данные, защищённые с помощью шифрования, должны быть восстанавливаемыми (заменяемыми) без использования аутентификации по отпечаткам пальцев (обязательно)

Когда приложение использует функцию аутентификации по отпечаткам пальцев для шифрования данных в приложении, дизайн приложения должен позволять восстанавливать (заменять) данные без использования аутентификации по отпечаткам пальцев. В целом, использование биометрической информации может привести к различным проблемам, включая конфиденциальность, сложность модификации и ошибки распознавания, поэтому лучше избегать полагаться исключительно на биометрическую информацию для аутентификации.

Например, если данные в приложении зашифрованы с помощью ключа, созданного с помощью функции аутентификации по отпечаткам пальцев, а ключ хранится в терминале, и пользователь впоследствии удаляет данные отпечатков пальцев, то ключ становится недоступным и его невозможно скопировать. Если данные не могут быть восстановлены без аутентификации по отпечаткам пальцев, существует значительный риск того, что данные станут непригодными для использования.

Кроме того, удаление биометрических данных не является единственным случаем, когда ключ, созданный с помощью функции аутентификации по отпечаткам пальцев, может стать недоступным. На Nexus 5X, например, если ключ создан с помощью функции аутентификации по отпечаткам пальцев и затем зарегистрирован как дополнительная биометрическая информация, ранее созданный ключ становится недоступен [30]. Также нельзя исключать возможность того, что ключ станет недоступным из-за ошибок распознавания датчика отпечатков пальцев, которые обычно позволяют правильно использовать ключ.

[30] Информация взята из версии от 1 сентября 2016 года. Это может быть изменено в будущем.

5.7.2.3 Уведомление пользователей о необходимости регистрации отпечатков пальцев для создания ключа (рекомендуется)

Чтобы создать ключ с помощью функции аутентификации по отпечаткам пальцев, необходимо зарегистрировать отпечатки пальцев пользователя на терминале. Разработчики должны помнить, что отпечатки пальцев представляют собой важные личные данные, и стремиться объяснить пользователям, почему использование данных отпечатков пальцев является необходимым или удобным.

Уведомление пользователей о необходимости регистрации отпечатков пальцев

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;
}

5.7.3 Дополнительные темы

5.7.3.1 Условия, необходимые для использования функции аутентификации по отпечаткам пальцев в приложениях Android

Чтобы приложение могло использовать функцию аутентификации по отпечаткам пальцев, должны выполняться два условия.

  • Отпечатки пальцев пользователя должны быть зарегистрированы в терминале.
  • Ключ, связанный с зарегистрированными отпечатками пальцев, должен быть создан.

Регистрация отпечатков пальцев пользователя

Информация об отпечатках пальцев может быть зарегистрирована только через меню настроек «Безопасность»; обычно приложение не может выполнить процесс регистрации отпечатков пальцев. Поэтому, если приложение пытается использовать функцию аутентификации по отпечаткам пальцев без зарегистрированных отпечатков пальцев, приложение должно направить пользователя в меню настроек и побудить его зарегистрировать свои отпечатки пальцев. В этом случае приложение должно предоставить пользователю некоторые объяснения, объясняющие, почему использование информации об отпечатках пальцев является необходимым и удобным.

Также, в качестве предварительного условия для регистрации отпечатков пальцев, терминал должен иметь альтернативный механизм блокировки экрана. Если блокировка экрана отключена после регистрации отпечатков пальцев в терминале, зарегистрированная информация об отпечатках пальцев будет удалена.

Создание и регистрация ключа

Чтобы связать ключ с зарегистрированными отпечатками пальцев, используйте экземпляр 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 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-android-app-sec-guidebook.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-android-app-sec-guidebook.git
oschina-mirror
wizardforcel-android-app-sec-guidebook
wizardforcel-android-app-sec-guidebook
master