Біаметрычная аутэнтыка з падзею на iOS і Android з ключамі, прыўязанымі да апаратуры
Толькі Face ID сама па сабе нічога не падтверджае для вашага сервера. Отрымайцеся ад викорыстоўвання Secure Enclave і ключоў Android Keystore для падписвання одноразовых запитоў з мэтай рэальнай падыгранай аутантыкацыі.
Крыніцы: Biometrics, the Secure Enclave, and Auth Tokens: Three Ideas That Sound the Same But Aren’t
У характэрыстыках продукту частаюць згадкі пра тое, што «Face ID адзначае дапрыяж да прыемлівання аплікацыі», і для большасці корыстувачаў такой апіс ёсць дастатнім. Аднак калі йдэца пра стварэнне систем платежаў, ведамасцей пра стан здароў’я, адміністрацыйных панелей чы процэсаў аблогіну, такі падход закрывае важны аспект: біаметрычны скан ніколі не прабывае да вашага бэкенду, ніколи не стварае токена, і ніколи не передае вашаму коду шаблона твары чы відблеску пальца. Насамперад, добра спроектаваная аплікацыя отрымае права на викорыстанне західванага апарату для працы з прыватным ключам, якія ваш код не можа прачытаць; гэты ключ можа падписаць ексклюзыўны вызов, які пасля таго пераканае сервер. У гэтым кяліку раздзелены тры падходы, якія часта сплываюць адзін з іншым (біаметрычныя запиты, ключы, падтрымваныя апаратам, і токены аутэнтыкацыі), і показан працэс регистрацыі заўважка-падпису на обох платформах.
Чаму сам токен ёсць слабым аспектам на мобільным прыстрое
Мобільныя дапрынкі працуюць на апаратнасці, якой кантролюе ўжоўка, а не вы. Тэлфоны губяцца, экраны блакуецца, падчас разработкі выкарыстоўваюцься інструменты для діагностикі, а пры наявнасці root-праваў чы ў разе jailbreak устройства можа адкрываць гораздаў больш інфармацыі пра вашы процес, чым вам хацелася.
Незважаючы на все гэта, чулівы канец-пункт павінен верыць точнаму твэрджэнню: калінкі выходзіць з тэлфона, які мае клячу, яку сервер раней зарэгістраваў, і чалавек, які нешта часам раней затвердзіў выкарыстоўванне гэтай клячы.
Пораўняйце гэта з фразай «гэты запит несе токен». Будзь-які значэнне, яке знаходзіцца ў памяці чы сховішчы дапрынка, можа быць скопіявана і перадаўнае з іншага месца. Прыватная кляча, якая генеруецца ў захіщанай апаратнасці і не можа быць выэкспортаваная, ёсць набліжнае больш сложным цэлям, адтолькі як ў крадзеўцы значыць атакаваць саму апаратнасць, а не проста прачытаць строку.
Перш чым што-небудзь ствараць, корыстна назваць, што самэў кожны элемент падтверджвае:
- Біаметрычныя методы аутэнтыкацыі: телефон падтрымлеў Face ID, Touch ID або супэрнаёсныя біаметрычныя методы Android.
- Захоўваныя апаратныя канцэлеры: захаваныя прыватныя канцэлеры ствараюць падпісы.
- Токены аутэнтыкацыі: ваш сервер надае права на сесію або які-небудзь доступ.
Надзеяны дизайн выкарыстоўвае ўсе тры методы, кожны з якіх для сваёй задачы.
HTTPS заходзіць канал, а не ідэнтычнасць
HTTPS шифруе трафік межаў прыложэнням і вашай API, таму людзі, якія выкарыстоўваюць сеть кафе, не можу лёгка чытаць аб змяніць запиты.
phone ── encrypted HTTPS connection ──► server
Гэта ўмовна неабходна, але сама по сабе недастатня. Якщо зловмешчык вялікі час тады валідны токен, TLS будзе аддаўаць гэты вкрадзены токен вашаму серверу на адпаведны і безпечны спосаб. Ніч гэта не паведамляе серверу, чы роўна токен прыйшоў з легітым прыстрою чы з копіі.
Такім чынам, базовыя прыемы: выкорыстоўваць HTTPS у кожнай вызове, перавершаць сертыфікаты стандартным спосабам, падтрымляць апштэнды TLS з актуальнымі патчамі, а таксама дадаць додатковы механізм аутэнтыкацыі, які надае інформацыю, яку можна пераканацца, пра прыстрой і дзеянне пользователя.
Фіксацыя сертыфікатаў — гэта спецыяльны інструмент
Фіксацыя обмежвае прыстрой адной вядомай ідэнтычнасці сертыфіката або публічнага канцэляра. У строго контролюваемых дапрыемах гэта можа зменшыць ризык атак типу «чалавек у сяродзіні».
Але гэта не дапамагае прымусіць токен-носільнік паводзіцца як аутентыкацыйны дакумент, падтрымваны апаратам. Кроме таго, гэта несе рэальныя операцыйныя рызыки: якщо вы падаўзіце некоректную фіксацыю або прастаяце заменіць сертыфікат, кожная установленае копія дапрыема адразу ж перестане вяртацца да вашага API. Адмаўляйце яго выкарыстоўванне толькі тады, калі ваша модэль апасцероғаў цього патрабуе і ваш процес выпуску можа надзейна кераваць заменай ключоў, і ніколі не вважайце яго заменай аутэнтыкацыі, прыязначанай для конкретнага прыстрою.
Біаметрычны праграматык — гэта толькі локальна адпаведна або няўпаведная адказа
У iOS прыкладніця прасіць LAContext паказаць экран системнай аутантыкаціі; у Android адпаведны элемент — BiometricPrompt. Аператывная система адбывае скануванне і паведамляе пра успех або няўспэх. Наводзімы ўрывак на мове Swift: ён пераканальваеся ў правілы викорыстоўвання толькі біаметрычных дадзеных з абясненням і запускае пераказ, якщо пераканальванне успеху.
let context = LAContext()
let policy = LAPolicy.deviceOwnerAuthenticationWithBiometrics
context.evaluatePolicy(policy, localizedReason: "Approve this transfer") { success, error in
guard success else { return }
startTransfer()
}
У вашам кодзе ніколи не будуць відображацца геаметрыя лява або знімкі відблескаў. Apple описвае LocalAuthentication як прылад, який работае з Secure Enclave і вяртае прыкладніцы толькі рэзультат успеху або няўспэху (інструкцыя да фрэймворку LocalAuthentication).
Гэтага цалкам дастатнек для захавання прыватных даных усередзіне прыкладніцы. Але як доказ для сервера гэта недастатнья з трохоў прычын:
- У рэзультате паказваецца толькі „прыстрой прыняў перакананне“; у ям няма жадных мэтадаў пра тое, хто чы ў якому рэчынку.
- У бэкендзе няма можлівасці пераканацца ў булевым значэнні, якое ствараецца на кліянтзе.
- Якщо процес прыложэння будзе атакаваны, зловершальнік можа праскочыць чы падрабаваць функцію адпаведзення і проста пракрыстаць вялік, які ўжо існуе.
Галоўная мысль з гэтага патэрану — success ёсць проста флаг у вашай сопраўднай памяці. Болей надзеяны дизайн выкарыстоўвае біаметрычную перакананнę, каб разблокаваць адну крыптаграфічную операцыю, чыяе выходна значэнне сервер можа самастоятельна пераканацца.
Хардверныя хранілішчы клячоў не прабачаюць прыватную клячу ў вашым процесе
У прыладах Apple ёсць Secure Enclave — айсалаваны падсістэм, які можа ствараць і выкарыстоўваць прыватныя кантрольнікі, не прабачаючы ніколі самых кантрольнікаў главнаму процэсару прылада. За інструкцыямі Apple, кантрольнік застаецца ўнутры Secure Enclave, а прылад толькі получае выходныя данні, такія як падпісы (Інструкцыя Apple пра Secure Enclave).
Адэкватным аналагам на іншай платформе ёсць Android Keystore. Залежна ад апаратуры, клучы можаць быць захаваны ў аб’екте Trusted Execution Environment (TEE) або ў спецыяльным захіщаным элементе StrongBox. Будзьце абераглівы ў называнні: „Titan M“ — це чып у тэлефонах Google Pixel, а не загальная API Android, і не трэба прыпускать, што кожны прыстрой яго мае. З точкі зору дапрыямоўкі, важлівае — гэта тое, як захаваны клуч і якія правілы викорыстоўвання да яго прызначаны.
Для дзеяння высокай ценнасці клуч должен адпавядаць чатыром правілам:
- Ён ствараецца на самэм гэтым прыстрое.
- Кожныя выкарыстоўванні трэбуюць свежага, надзеянага біометрычнага паверкання.
- Прыватную частку ніколі не можна экспортуваць.
- На серверы захоўвана толькі публічная частка клуча.
У Android BiometricPrompt.CryptoObject можа рэгулюваць аператыўную операцыю толькі тады, калі клас аутантыкатора ў значэнні BIOMETRIC_STRONG, а ключ можа быть настроены так, каб патрабаваць новага затверджэння ў кожны раз, колі яго викорыстоўваюць (інфармацыя пра BiometricPrompt, аптаварызацыя Keystore).
Пратакол: зарэўнаваць ключ аднойчы, пасля чаго падписваць новыя запиты
Усія процесы складаюцца з двух фаз: рэўнавання і викорыстоўвання.
Рэўнаванне
- Аплікацыя стварае пару ключоў, падтрымваную апаратам.
- Яна завантажае публічны ключ на сервер через HTTPS.
- Сервер фіксуе публічны ключ разам з аднойчынай та ідэнтыфікаторам прыстрою.
- Прыватны ключ застаецца на тэлефоне, у захіщаным апаратным механізме.
Адрасаванне публічнага клячу нешкодна: ён можа пераканаліцаваць падпісы, але не можа іх стварыць. Толькі прыватны кляч можа падпісваць, і ён ніколі не выходзіць за межы захаванага апаратнага з’яву.
Затверджэнне чутлівага запиту
- Дзеянне прасіта ад сервера разовыя вэлкаментныя данні, выбраныя адзелёва.
- Пользователь выпалняе біаметрычны запит.
- Захаваны апаратны з’яв выдае падпіс на гэтыя вэлкаментныя данні.
- Дзеянне вяртае ID вэлкаментных данняў і падпіс.
- Сервер пераканаліцавае падпіс за дапамою збераганага публічнага клячу.
- Сервер прымея або адхіляе дзеянне, і можа пасля таго выдаты токен.
Сама проблема заключаецца ў тым, дзе большасць рэалізацый дапускаюць памылкі. Падпис должен быць адбывацца наявнасцю случайных дадзеных, шырока выгораць і выкарыстоўваны толькі адназначна. Ён таксама павинен быть прыязджаны да абліквату, да конкрэтнага ключа прыстрою і да дзеяння, якое апраўляецца (на прыклад, „Пераказаць 200 EUR на аблікват X“). Якщо прыйміць які-небудзь з этых пунктаў, захоплены падпис можна будзе паўтарна выкарыстоўваць для іншага запиту, што ёсць класычным атакам паўтарнага выканання. Прывязка да дзеяння таксама запобегае тому, каб падпис, заслужаны для безнебяжной операцыі, быў перенаправлены на небяжную.
iOS: ключ Secure Enclave, які выкалікае адбор Face ID ў кожны момент выкорыстання
У iOS ключ ствараецца безпасна ўнутрь Secure Enclave і прыкладзаецца об’ект кантролю доступу, які выказвае патрабаванне да біаметрычных дадзеных кожны раз, калі ключ выкарыстоўваецца. У коде на Swift, паказанам нижэй, можна разгледзець тры варыянты. kSecAttrAccessibleWhenUnlockedThisDeviceOnly не дазволяе ключу пераходзіць у резервныя копіі чы іншыя прыстроі. Флагі .privateKeyUsage і .biometryCurrentSet выказваюць патрабаванне да біаметрычнай адзначкі для падписвання і прыяўляюць ключ да актуальна зарэгістраваных твароў чы пальцоў. А kSecAttrTokenIDSecureEnclave ёсць тым, што размешчае ключ у апаратнай частцы; Secure Enclave падтрымляе толькі ключі з 256-бітным эліптычным выгнутым крэсам (P-256), таму тип і размах ключа заданы так, як ёсць.
// 1. Create access control requiring Face ID / Touch ID for every use
var error: Unmanaged<CFError>?
guard let accessControl = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
[.privateKeyUsage, .biometryCurrentSet],
&error
) else { return }
// 2. Generate the key pair in the Secure Enclave
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: "com.example.keys.transfer",
kSecAttrAccessControl as String: accessControl
]
]
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { return }
Практычныя наследкі гэтаго элемента .biometryCurrentSet заключаюцца у тым, што рэўістрацыя новага відблеску пальца або скасаванне Face ID унічтожае ключ. Зазвычай гэта самэ тое, чаго вы хочаце для платежаў, але гэта значыць, што ваша прыкладна програма павінна адпрацоўваць ситуацыю з відсутнасцю ключа адпаведна і практычна перакінуць корыстніка на паўтарную рэўістрацыю.
Завантажыце публічны ключ пасля таго, як корыстнік завершыў стандартны вход у акаунт. Пазней, калі сервер выдае вялікі набор дадзеных для пераказу, падпісце іх прыватным ключам. Вы сабе не пакажаеце спрашоў: заводзячыся з пазнакамі кантролю доступу, вызов падпісаў автаматычна актывае Face ID або Touch ID.
let algorithm: SecKeyAlgorithm = .ecdsaSignatureMessageX962SHA256
var signError: Unmanaged<CFError>?
// 3. This call automatically triggers the Face ID prompt because of the accessControl flags
guard let signature = SecKeyCreateSignature(
privateKey,
algorithm,
challengeData as CFData,
&signError
) else { return }
api.approve(challengeId, signature)
Якщо корыстнік анулюе процэс сканавання або ён не выйдзе, SecKeyCreateSignature вяртае значэнне nil, і не існуе падпіса, які можна было б адправіць, таму не існуе пазнаки успеху, якую мог бы змяніць хакер.
Android: ключ Keystore, які адкрыты через BiometricPrompt
Котлін, прыведзеный нижэй, стварае ключ EC для падпісаў толькі ў прадастчыку AndroidKeyStore. Метод setUserAuthenticationRequired(true) змушвае абавязковаю аутентыкацыю, а setUserAuthenticationParameters(0, AUTH_BIOMETRIC_STRONG) задае тэрмін дзейнасці равным нулю секундам, што означае, што для кожнага выкарыстання трэба новая сильная біометрычная перапрацоўка, а не пэрыод паузы пасля пярэдньага адзначэння.
val spec = KeyGenParameterSpec.Builder(
"transfer-key",
KeyProperties.PURPOSE_SIGN
).setDigests(KeyProperties.DIGEST_SHA256)
.setUserAuthenticationRequired(true)
.setUserAuthenticationParameters(
0,
KeyProperties.AUTH_BIOMETRIC_STRONG
).build()
val generator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_EC,
"AndroidKeyStore"
)
generator.initialize(spec)
val publicKey = generator.generateKeyPair().public.encoded
Пасля таго, як корыстнік нормальна заўяжаеся, адправіце закодаваны publicKey на сервер і зберагучы яго разам з дакументамі корыстніка і прыстрою.
Калі сервер пазней выдае запит на перадачу, ініцыявуйце об’ект Signature, загорніце яго ў CryptoObject і перадайце гэта запиту. Ляжыць ствараць падпіс толькі ўнутры метады onAuthenticationSucceeded, прадаўшы там байты запиту.
val signature = Signature.getInstance("SHA256withECDSA")
signature.initSign(privateKey)
val crypto = BiometricPrompt.CryptoObject(signature)
prompt.authenticate(promptInfo, crypto)
override fun onAuthenticationSucceeded(result: AuthenticationResult) {
val signed = result.cryptoObject!!.signature!!
.apply { update(challenge) }.sign()
api.approve(challengeId, signed)
}
Дыялог не ўтварае межы безпекі; межай являецца CryptoObject. Кеш ключоў адмовіцца ад выканання операцыі падпісаў, якщо перакананне на адпаведнасць біаметрычным даным, якое даўно з’явілася, не будзе успешным, а сам матэріял ключа застанется ў захаваным кеше. Я ваша аплікацыя будзе зберагаць толькі рэзультат падпісаў.
На сервере пераканайцеся ў правамільнасці гэтага падпіса за дапамогою зарэўнаванага публічнага ключа. Якщо ён збяжыцца з невыпаленым, невыкарыстаным вызовам, затвердзіце пераказ чы выдаце токен короткага тэрміну дзейнасці, прызначаны для гэтай дзеяння.
Дзе ўсё ж такі належаць токены аутэнтыкацыі
Парабяранне падпісу, які ствароўваецца на апаратнай базе, не пазбавляе нас токенамі. Пасля такога парабярання выдача звычайнага токена доступу ёсць абсалютна логічной, адколі токены застаюцца практычным спосабам автарызаціі большай часткі трафіку API. Якщо вы праектуеце частку системы, якая карыстаецца токенамі, то прыняттыя тут рашэнні згаданыя ў нашай інструкцыі па стратэгіі токенав апдзейва таксама прыменяюцца.
Зберагайце гэтыя токены ў сховішчах, захаваных платформай: Keychain у iOS і сховішча, якія падтрымваюцца Keystore, у Android. Токены апдзейва длігага тыражу ніколі не трэба зберагаць у звычных настройках, звычных файлах чы сховішчах, доступных для JavaScript, што ўсё болюць значнае у дапытках React Native, дзе AsyncStorage є простым, але незахаваным стандартам.
Тады пытанне праектавання стае такім: як часта трэба запрашваць новы апаратны падпіс:
- Пры кожнам вызову API: практычна завжды занадта медленна і раздражаючая.
- Пры кожным запуску дапрабрамы: разумны выбар для захавання прыватных дапрабрам.
- Пры адзначэннях, рэедыцыі профіля, экспорце даных чы пры затверджэнні новага прыстрою: часта ўзьяўшаяся аптэма.
- Пры кожным выкарыстоўванні токена абнавлення: це карысна для аккаунтаў з вышэйшым рызыкам, якщо толькі корыстнік можа адразу прымусіцца да дзеянняў, якія прыказваюцца.
Спачатку спрыяйце падпис як дапаможны доказ, а токен — як кароткачасова разрэшэння, якае выліваецца з яго.
Меры клучоў, падтрымваных апаратам
Гэты падход є эфектывным, але ён не ўсепрацоўваючы:
- Ён не дапамагае проты законныя корыстніка, які сам адзначае свой тэлфон і затверджвае шкодзіцельныя дзеяння, напрыклад пад тым пачынаннем соцыяльнага інжыніроўвання.
З самага пачатку планавайце шлях вярнення дахоўкі, пры чым яго трэба спецыяльна зробіць медленнейшым і более рэгулярна перацяроўваным, чым звычайны шлях. Калі зникае ключ прыстрою, экран блокавання перазначаецца або змінюецца процес рэўістрацыі біметрычных даных, ваша аплікацыя павінна быць гатовая да рэўістрацыі новага ключа, а ваш сервер — анулюваць стары. У дасягліх дакументах Android адзначаецца, што ключы, прыязваныя да аутэнтыкацыі, можу быць перманентна анульваныя, калі змінюецца захіщанный экран блокавання або процес рэўістрацыі біметрычных даных, залежна ад таго, як быў настроены ключ (справака KeyProtection.Builder).
Як passkeys адносяцца да гэтага дзейства
Паскоды базуюцца на той жа самай аднойчыні: пара публічных/прыватных канцэлараваў і запыт сервера, падпісанный прыватным канцэларавам. Для заходу на веб-сайты і адзеныя яны зазвычай ўтвараюць найкращая можліва альтернатыва, таму што операцыйная система і платформа абрабатваюць большую частку складных задач. Паскоды — это стандартызаваны, міжплатформеный пратакол, які будуецца на такым стыле падпісаў, падтрымваных апаратнай часткаю. Є адна нюанса: багато паскодаў сінхронізуюцца между прыстроямі корыстніка через менеджар пароляў платформы, таму яны не завжды прыязначаны для аднаго тэлефона, як канцэларавы з Кешбокса аднойчыні або Secure Enclave, якія не можна экспортаваць.
Эта разліка парадоксальна, адказваючы на простая разбіўка. Выбірайце ключ дапрыямоўвання прыстроя, калі натыўны дапрыямоўвання патрабуе падтверджэння, прыязначанага конкретнаму прыстрою, для певной дзеяння. Для сучасных спосабаў заходжання без пароляў, якія можа падтрымаць ваш продукт, выбірайце ключы доступу. У будзь-якам случае задача сервера застаецца той самы: паверыць падпис, выкарыстоўваючы абявлены ключ, якому ён вярыць.
Выбіранне правага інструмента для кожной патрэбы
- Захаванне дадзеных пад час перадачы: HTTPS.
- Зберагчэнне стану заходжання пользователя: токен доступу з короткім тымчасовым періодам дзеяння плюс захаваны токен апавежэння.
- Заблокаванне прыватнага кантэнту пад час ачынення дапрыямоўвання: Face ID, Touch ID або BiometricPrompt.
- Апраўленне платежа або іншага дзеяння з высокым рызыкам: падпис на апаратнай базе, захіщаны біаметрычнымі данымі.
- Заходжання без пароляў: ключы доступу.
- Зменшэнне рызыку перехоплення пакетаў TLS: фіксацыя сертыфіката.
Галоўныя выводы
Сканаванне Face ID і відблескаў пальцоў не атверджаюць запыт з бэкенду. Яны разрываюць права на вжытак ключа; західная апаратура выкарыстоўвае гэты ключ для падписвання новага запыту сэрвера; а сэрвер пераканальвае падпис пры вынікненні рашэння, што можа рабіць корыстнік.
- Біаметрыя: локальнае атверджэнне, невидма для сэрвера.
- Апаратны ключ: доказ наявнасці, які не можа быць скопіяваны з прыстрою.
- Токен: трымкамернае разрэшэнне сэрвера на корыстування.
Зберагчыце гэтыя ролі адзінаковымі, прыязначайце кожны запыт да аднаго аккаунта, ключа і дзеяння, а таксама планавайце недзейнасць і вярнэнне ключа. Рэзультатам будзе дизайн мобільной атрыбуцыі, які лёгчэй разумець і значна сложней падрабаць.