使用iOS和MACOS上的安全飞地签名,验证,加密和解密。
支持faceID,TouchID,设备通过代码和应用程序密码。
使用安全框架可能会有些混乱。这就是为什么我创建这个。您可以将其用作示例代码和指导,也可以将其用作微框架。
我发现很难弄清楚如何使用Swift 3中的SecKeyRawVerify , SecKeyGeneratePair和SecItemCopyMatching c apis,但是由于出色的Swift功能,实现非常直接。
只需将Sources/EllipticCurveKeyPair.swift和Sources/SHA256.swift拖放到您的Xcode Project中即可。
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 ]
} ( ) )在这种情况下,您需要记住将Config Object中的token变量设置为.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
}签名时,您也可以通过lactext对象
do {
let digest = " some text to encrypt " . data ( using : . utf8 ) !
let encrypted = try KeyPair . manager . encrypt ( digest , hash : . sha256 )
} catch {
// handle error
}您也可以使用公共密钥在其他设备/OS/平台上加密。如果您想了解有关如何以Secure Enclave理解的格式加密的所有详细信息,那么您绝对需要阅读@DSChuetz的出色文章!
https://darthnull.org/security/2018/05/31/secure-enclave-ecies/
do {
let encrypted = ...
let decrypted = try KeyPair . manager . decrypt ( encrypted , hash : . sha256 )
let decryptedString = String ( data : decrypted , encoding : . utf8 )
} catch {
// handle error
}解密时您也可以通过lactext对象
最常见的事情是捕获与
与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个文件。
Security framework, Swift 3, Swift 4, Swift, SecKeyRawVerify, SecKeyGeneratePair, SecItemCopyMatching, secp256r1, Elliptic Curve Cryptography, ECDSA, ECDH, ASN.1, Apple, iOS, Mac OS, kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyTypeEC, kSecAttrTokenIDSecureEnclave, lactext,localauthentication,faceid,face id,touchID,触摸ID,应用程序密码,设备PIN,DEVICEPIN
TrailofBits不久前发布了一些Objective-C代码,这对您有很大的帮助!感谢您分享Tidas和SecureenclaveCrypto。他们还收到了其他一些最有趣的项目。检查一下!
他分享了SOM非常有价值的见解,以适当的der X.509格式出口公共密钥。
SHA256类(最初是SHA2.swift )是在MarcinKrzyżanowski的宝贵隐式库中找到的。为了将其划分至最低限度,该课程已进行了大量更改。
为什么在模拟器上没有提示我使用触摸ID /设备引脚的提示?
模拟器没有任何安全的飞地,因此试图访问它只会导致错误。如果将
fallbackToKeychainIfSecureEnclaveIsNotAvailable设置为true,则将私钥存储在模拟器上的键链中,从而可以易于测试您在模拟器上的应用程序。
我在哪里可以学到更多?
在WWDC 2015上查看有关安全性的视频,或单击此处跳过有关安全飞地的部分。
为什么它包裹在枚举中?
我尝试在XCode中平衡所需的拖放文件,并同时支持迦太基和Cocoapods等依赖性经理。如果您有更好的想法或不同意这个决定,我很乐意讨论替代方案:)
我们会吗?聆听您对此图书馆的看法。您喜欢还是不喜欢。如果您想改进一些问题,请提出问题。您可以在Twitter和其他地方作为@hfossli与我联系。 ?