Firme, verifique, cifre y descifra usando el enclave seguro en iOS y macOS.
Admite FaceID, TouchID, código de aprobación del dispositivo y contraseña de aplicación.
Usar el marco de seguridad puede ser un poco confuso. Por eso creé esto. Puede usarlo como código de ejemplo y orientación o puede usarlo como un micro marco.
Me pareció complicado descubrir cómo usar las apis SecKeyRawVerify , SecKeyGeneratePair y SecItemCopyMatching C en Swift 3, pero la implementación es bastante sencilla gracias a las impresionantes características rápidas.
Simplemente arrastre Sources/EllipticCurveKeyPair.swift y Sources/SHA256.swift archivo en su proyecto xcode.
pod EllipticCurveKeyPair github "agens-no/EllipticCurveKeyPair" Hay muchas posibilidades geniales con enclave seguro. Aquí hay algunos ejemplos
Solo disponible en iOS 10 y más
Un caso de uso podría ser
Para más ejemplos, consulte la aplicación de demostración.
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 )
} ( )
}También puede alojarse con gracia para usar el llavero si no está disponible un enclave seguro utilizando diferentes banderas de control de acceso:
let privateAccessControl = EllipticCurveKeyPair . AccessControl ( protection : kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly , flags : {
return EllipticCurveKeyPair . Device . hasSecureEnclave ? [ . userPresence , . privateKeyUsage ] : [ . userPresence ]
} ( ) ) En ese caso, debe recordar establecer la variable token en el objeto Config a .secureEnclaveIfAvailable .
do {
let key = try KeyPair . manager . publicKey ( ) . data ( ) . DER // Data
} catch {
// handle error
}Ver la aplicación de demostración para el ejemplo de trabajo
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
}También puede pasar un objeto lacontext al firmar
do {
let digest = " some text to encrypt " . data ( using : . utf8 ) !
let encrypted = try KeyPair . manager . encrypt ( digest , hash : . sha256 )
} catch {
// handle error
}También puede cifrar en un dispositivo/OS/plataforma diferente utilizando la clave pública. Si desea saber todos los detalles sobre cómo cifrar en un formato que entiende el enclave seguro, ¡definitivamente necesita leer este gran artículo de @DSChuetz!
https://darthnull.org/security/2018/05/31/secure-enklave-ecies/
do {
let encrypted = ...
let decrypted = try KeyPair . manager . decrypt ( encrypted , hash : . sha256 )
let decryptedString = String ( data : decrypted , encoding : . utf8 )
} catch {
// handle error
}También puede pasar un objeto de lacontext al descifrar
Lo más común es atrapar un error relacionado con
Con 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 ) " )
} Con 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 ) " )
} Para inspeccionar las consultas que van y vienen al llavero, puede imprimir para consolar cada mutación que esta biblioteca hace en llavero como este
EllipticCurveKeyPair . logger = { print ( $0 ) } En la aplicación de demostración, verá que cada vez que cree una firma se registre alguna información útil para la consola.
Salida de ejemplo
#! /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.datPara ejecutar este script puedes
verify.shchmod u+x verify.sh./verify.shEntonces deberías ver
Verified OKPD: Este script creará 4 archivos en su directorio actual.
Marco de seguridad, Swift 3, Swift 4, Swift, SecKeyverify, SecKeyGeneratePair, SecitemCopyMatching, SECP256R1, Criptografía elíptica de la curva, ECDSA, ECDH, ASN.1, Apple, iOS, Mac OS, KsecattrkeyPeecsecrimerandom, KsecattrkeyTypeec, ksecattrokenidsecureenclave, lacontext, localauthentication, faceID, facial ID, touchID, ID de touch, contraseña de aplicación, pin de dispositivo, dispositivo de dispositivo
TRAILOFBITS publicó un código Objective-C hace un tiempo que fue de gran ayuda. Gracias por compartir TIDAS y SecureenClaVecrypto. También obtuvieron otros proyectos más interesantes. ¡Míralos!
Compartió información muy valiosa con respecto a la exportación de la clave pública en el formato DER X.509 adecuado.
La clase SHA256 (originalmente SHA2.swift ) se encuentra en la invaluable biblioteca Cryptoswift por Marcin Krzyżanowski. La clase ha sido muy alterada para despojarla al mínimo para lo que necesitábamos en este proyecto.
¿Por qué no se me solicita con Touch ID / Pin del dispositivo en el simulador?
El simulador no posee ningún enclave seguro y, por lo tanto, tratar de acceder a él solo conduciría a errores. Si establece
fallbackToKeychainIfSecureEnclaveIsNotAvailableatrue, entonces la clave privada se almacenará en KeyChain en Simulator, lo que también facilita probar su aplicación en el simulador.
¿Dónde puedo aprender más?
Mira este video en WWDC 2015 sobre la seguridad en general o haga clic aquí para omitir directamente a la sección sobre el enclave seguro.
¿Por qué está envuelto en una enumación?
Intento equilibrar la arrastre y la reducción de los archivos que necesita en Xcode y admitiendo gerentes de dependencia como Carthage y Cocoapods al mismo tiempo. Si tiene mejores ideas o no está de acuerdo con esta decisión, estoy feliz de discutir alternativas :)
Lo haríamos? Para escuchar su opinión sobre esta biblioteca. Si te gusta o no. Por favor presente un problema si hay algo que le gustaría ver mejorado. Puedes comunicarme conmigo como @hfossli en Twitter y en otros lugares. ?