Как безопасно реализовать биометрию с резервным паролем приложения для аутентификации подписи в Secure Enclave?IOS

Программируем под IOS
Ответить
Anonymous
 Как безопасно реализовать биометрию с резервным паролем приложения для аутентификации подписи в Secure Enclave?

Сообщение Anonymous »

Я хочу реализовать локальный процесс аутентификации, аналогичный многим банковским приложениям, в приложении iOS (Swift) для использования ключа в Secure Enclave:
  • По умолчанию вы устанавливаете пин-код для конкретного приложения.
  • После этого пользователь может включить биометрию (Face ID или Touch ID) для быстрой аутентификации.
  • После этого пользователь может подписать сообщение, используя свой закрытый ключ, хранящийся в Secure Enclave. либо с помощью биометрии, либо пользователь может вернуться к своему PIN-коду для конкретного приложения (либо по выбору, либо в случае отмены или невозможности распознания, например).
То, что я пробовал до сих пор
Флаг .applicationPassword для SecAccessControlCreateFlags показался разумным вариантом, позволяющим разрешить использование пароля, определенного приложением. использовал. Кроме того, набор возможных флагов также содержит ограничения, такие как devicePasscode и biometryCurrentSet, для установки ограничений доступа, которые можно даже комбинировать с помощью союзов. Следует отметить, что applicationPassword является не ограничением, а «опцией» согласно документации. Также не очень хорошо документировано, что на самом деле делает этот флаг. Тем не менее, я попробовал следующее:

Код: Выделить всё

let flags1: SecAccessControlCreateFlags = [.privateKeyUsage,
.biometryCurrentSet, .or, .applicationPassword]
let flags2: SecAccessControlCreateFlags = [.privateKeyUsage,
.biometryCurrentSet, .applicationPassword]

let access1 = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
flags1,
&error)
let access2 = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
flags2,
&error)
Похоже, что оба эти варианта работают по существу одинаково: сначала телефон запрашивает биометрическую проверку, а затем показывает подсказку, в которой вы можете ввести пароль приложения.
Я попробовал программно. предоставление пароля приложения с помощью LAContext.setCredential, и это работает нормально, поскольку запрос пароля приложения больше не будет отображаться, но iOS по-прежнему всегда будет запрашивать биометрические данные (даже при использовании флага .or) ). Таким образом, похоже, что флаг .or не работает так, как я надеялся, вместе с .applicationPassword. Тем не менее, эти политики контроля доступа, похоже, требуют, чтобы и биометрические данные, и пароль приложения передавались, что является хорошей возможностью, но не совсем тем, что я искал.
Я также пытался запретить соответствующие запросы, такие как Face ID приглашение не отображается с помощью LAContext.interactionNotAllowed, но это также не работает из-за флагов контроля доступа.
Базовая настройка
Для тестируя это, у меня есть простой Приложение iOS настроено со следующими функциями, полученными из документации Secure Enclave:

Код: Выделить всё

func getAccessControl() -> SecAccessControl {
var access: SecAccessControl?

access = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage,
.biometryCurrentSet,
.or,
.applicationPassword],
nil)!
return access
}

func generatePrivateKey() throws -> SecKey {
let context = LAContext()
context.setCredential("pwd123".data(using: .utf8), type: .applicationPassword)

let attributes: NSDictionary = [
kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits: 256,
kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,
kSecUseAuthenticationContext as String: context,
kSecAttrLabel: "label-for-reference",
kSecClass: kSecClassKey,
kSecPrivateKeyAttrs: [
kSecAttrIsPermanent: true,
kSecAttrApplicationTag: "tag-for-reference",
kSecAttrAccessControl: getAccessControl(),
]
]

var error: Unmanaged?
guard let privateKey = SecKeyCreateRandomKey(attributes, &error) else {
throw error!.takeRetainedValue() as Error
}

return privateKey
}

func retrieveKey(context: LAContext? = nil) -> SecKey? {
var attributes: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrLabel as String: "label-for-reference",
kSecMatchLimit as String: kSecMatchLimitOne,
kSecReturnRef as String: true,
]
if let context = context {
attributes[kSecUseAuthenticationContext as String] = context
}

var item: CFTypeRef?
let res = SecItemCopyMatching(attributes as CFDictionary, &item)

if (res == errSecSuccess) {
return (item as! SecKey)
} else {
return nil
}
}

func sign(data: String, key: SecKey) throws -> Data? {
if (SecKeyIsAlgorithmSupported(key, .sign, .ecdsaSignatureMessageX962SHA256)) {
var error: Unmanaged?
guard let signature = SecKeyCreateSignature(key,
.ecdsaSignatureMessageX962SHA256,
data.data(using: .utf8)! as CFData,
&error) as Data? else {
throw error!.takeRetainedValue() as Error
}
return signature
}
return nil
}
Затем я могу сгенерировать подпись, выполнив что-то вроде этого (опуская некоторые детали):

Код: Выделить всё

let privateKey = generatePrivateKey()

let context = LAContext()
context.setCredential("pwd123".data(using: .utf8), type: .applicationPassword)
let retrievedKey = retrieveKey(context)

var signedMessage: Data?
try signedMessage = sign(data: "abc", key: retrievedKey!))
Что я хотел бы узнать
Я хотел бы узнать, не упускаю ли я что-то в этой документации (в частности, по контролю доступа элементов связки ключей [безопасного анклава]), или, альтернативно, если есть особый обходной путь, позволяющий сделать эту работу. Например, я также подумал о том, чтобы объединить параметры доступа, например. Face ID --unlocks--> Код доступа к приложению --unlocks--> Закрытый ключ, чтобы код доступа к приложению мог быть предоставлен либо с помощью Face ID, либо непосредственно пользователем. Однако это приведет к загрузке пароля приложения в память (что в любом случае может не быть проблемой, если пользователь уже вводит свой пин-код в настраиваемом пользовательском интерфейсе). Как обычно решают эту проблему приложения со схожими функциями?

Подробнее здесь: https://stackoverflow.com/questions/740 ... to-authent
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»