Подписать, проверить, зашифровать и расшифровать, используя защищенный анклав на iOS и macOS.
Поддерживает FaceID, TouchID, Device Pass Code и пароль приложения.
Использование структуры безопасности может быть немного запутанным. Вот почему я создал это. Вы можете использовать его в качестве примера кода и руководства, или вы можете использовать его в качестве микроммуры.
Мне было сложно выяснить, как использовать API SecKeyRawVerify , SecKeyGeneratePair и SecItemCopyMatching C в Swift 3, но реализация довольно проста благодаря потрясающим функциям Swift.
Просто перетащите Sources/EllipticCurveKeyPair.swift и Sources/SHA256.swift файл в свой проект Xcode.
pod EllipticCurveKeyPair github "agens-no/EllipticCurveKeyPair" Есть много отличных возможностей с безопасным анклавом. Вот несколько примеров
Доступен только на iOS 10 и выше
Вариант использования может быть
Для получения дополнительных примеров см. Демо -приложение.
struct KeyPair {
static let manager : EllipticCurveKeyPair . Manager = {
let publicAccessControl = EllipticCurveKeyPair . AccessControl ( protection : kSecAttrAccessibleAlwaysThisDeviceOnly , flags : [ ] )
let privateAccessControl = EllipticCurveKeyPair . AccessControl ( protection : kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly , flags : [ . userPresence , . privateKeyUsage ] )
let config = EllipticCurveKeyPair . Config (
publicLabel : " payment.sign.public " ,
privateLabel : " payment.sign.private " ,
operationPrompt : " Confirm payment " ,
publicKeyAccessControl : publicAccessControl ,
privateKeyAccessControl : privateAccessControl ,
token : . secureEnclave )
return EllipticCurveKeyPair . Manager ( config : config )
} ( )
}Вы также можете изящно запасаться для использования клавиши, если защищенный анклав недоступен с помощью различных флагов управления доступом:
let privateAccessControl = EllipticCurveKeyPair . AccessControl ( protection : kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly , flags : {
return EllipticCurveKeyPair . Device . hasSecureEnclave ? [ . userPresence , . privateKeyUsage ] : [ . userPresence ]
} ( ) ) В этом случае вам нужно помнить, чтобы установить переменную token в объекте Config .secureEnclaveIfAvailable
do {
let key = try KeyPair . manager . publicKey ( ) . data ( ) . DER // Data
} catch {
// handle error
}См. Демо -приложение для рабочего примера
do {
let key = try KeyPair . manager . publicKey ( ) . data ( ) . PEM // String
} catch {
// handle error
} do {
let digest = " some text to sign " . data ( using : . utf8 ) !
let signature = try KeyPair . manager . sign ( digest , hash : . sha256 )
} catch {
// handle error
}Вы также можете передать объект Lacontext при подписании
do {
let digest = " some text to encrypt " . data ( using : . utf8 ) !
let encrypted = try KeyPair . manager . encrypt ( digest , hash : . sha256 )
} catch {
// handle error
}Вы также можете зашифровать на другом устройстве/ОС/платформе, используя открытый ключ. Если вы хотите узнать все подробности о том, как зашифровать в формате, который понимает защищенный анклав, тогда вам определенно нужно прочитать эту замечательную запись @dschuetz!
https://darthnull.org/security/2018/05/31/secure-enclave-esies/
do {
let encrypted = ...
let decrypted = try KeyPair . manager . decrypt ( encrypted , hash : . sha256 )
let decryptedString = String ( data : decrypted , encoding : . utf8 )
} catch {
// handle error
}Вы также можете передать объект Lacontext при расшифровке
Наиболее распространенным является улавливать ошибку, связанную с
С do/catch :
do {
let decrypted = try KeyPair . manager . decrypt ( encrypted )
} catch EllipticCurveKeyPair . Error . underlying ( _ , let underlying ) where underlying . code == errSecUnimplemented {
print ( " Unsupported device " )
} catch EllipticCurveKeyPair . Error . authentication ( let authenticationError ) where authenticationError . code == . userCancel {
print ( " User cancelled/dismissed authentication dialog " )
} catch {
print ( " Some other error occurred. Error ( error ) " )
} С if let :
if case let EllipticCurveKeyPair . Error . underlying ( _ , underlying ) = error , underlying . code == errSecUnimplemented {
print ( " Unsupported device " )
} else if case let EllipticCurveKeyPair . Error . authentication ( authenticationError ) , authenticationError . code == . userCancel {
print ( " User cancelled/dismissed authentication dialog " )
} else {
print ( " Some other error occurred. Error ( error ) " )
} Чтобы осмотреть вопросы, переходящие взад -вперед в ключ -майне, вы можете распечатать, чтобы утешить каждую мутацию, которую эта библиотека делает на ключах, как это
EllipticCurveKeyPair . logger = { print ( $0 ) } В демонстрационном приложении вы увидите, что каждый раз, когда вы создаете подпись, какая -то полезная информация регистрируется в консоли.
Пример вывода
#! /bin/sh
echo 414243 | xxd -r -p > dataToSign.dat
echo 3046022100842512baa16a3ec9b977d4456923319442342e3fdae54f2456af0b7b8a09786b022100a1b8d762b6cb3d85b16f6b07d06d2815cb0663e067e0b2f9a9c9293bde8953bb | xxd -r -p > signature.dat
cat > key.pem << EOF
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdDONNkwaP8OhqFTmjLxVcByyPa19
ifY2IVDinFei3SvCBv8fgY8AU+Fm5oODksseV0sd4Zy/biSf6AMr0HqHcw==
-----END PUBLIC KEY-----
EOF
/usr/local/opt/openssl/bin/openssl dgst -sha256 -verify key.pem -signature signature.dat dataToSign.datЧтобы запустить этот сценарий, вы можете
verify.shchmod u+x verify.sh./verify.shТогда вы должны увидеть
Verified OKPS: Этот скрипт создаст 4 файла в вашем текущем каталоге.
Структура безопасности, Swift 3, Swift 4, Swift, SeckeyRawVerify, SeckeyGeneratePair, SeciTemCopyMatching, Secp256R1, Elliptic Crve Cryptography, ECDSA, ECDH, ASN.1, Apple, IOS, Mac OS, KSECATTRKEYTYPEECSECPRIMERANDOM, KSECATTRKETTRKETYPEECTECTTRKEYPEECTTRKEYPEECTTRKEYPEECTTR Ksecattrtokenidsecureenclave, Lacontext, LocalAuthentication, FaceID, идентификатор лица, TouchId, Touch ID, пароль приложения, PIN -код устройства, DevicePin
Trailofbits опубликовал какой-то код Objective-C, который был для большой помощи! Спасибо, что поделились TIDAS и SecureEnClaveCrypto. Они также получили некоторые другие самые интересные проекты. Проверьте их!
Он поделился Some очень ценным пониманием в отношении экспорта открытого ключа в правильном формате Der X.509.
Класс SHA256 (первоначально SHA2.swift ) находится в бесценной библиотеке CryptoSwift Марцина Крижановски. Класс был сильно изменен, чтобы поднять его до минимума для того, что нам нужно в этом проекте.
Почему меня не предлагают с помощью сенсорного идентификатора / штифта устройства на симуляторе?
Симулятор не обладает каким -либо безопасным анклавом и, следовательно, пытается получить доступ к нему просто привести к ошибкам. Если вы установите
fallbackToKeychainIfSecureEnclaveIsNotAvailabletrue, то закрытый ключ будет храниться в ключах на симуляторе, что также легко проверить ваше приложение на симуляторе.
Где я могу узнать больше?
Посмотрите на это видео на WWDC 2015 о безопасности в целом или нажмите здесь, чтобы пропустить прямо в раздел о безопасном анклаве.
Почему это обернуто в перечисление?
Я стараюсь сбалансировать перетаскивание файлов, которые вам необходимы в XCode, и одновременно поддерживают менеджеры по зависимостям, такие как Carthage и Cocoapods. Если у вас есть лучшие идеи или вы не согласны с этим решением, я рад обсудить альтернативы :)
Мы бы? Чтобы услышать ваше мнение об этой библиотеке. Вам нравится или нет. Пожалуйста, подайте проблему, если есть что -то, что вы хотели бы увидеть улучшенным. Вы можете связаться со мной как @hfossli в Твиттере и в других местах. ?