iOSとmacOSのセキュアエンクレーブを使用して、署名、検証、暗号化、復号化。
FaceID、TechID、デバイスパスコード、アプリケーションパスワードをサポートしています。
セキュリティフレームワークを使用することは、少し混乱する可能性があります。だから私はこれを作成しました。サンプルコードとガイダンスとして使用するか、マイクロフレームワークとして使用することもできます。
SecKeyRawVerify 、 SecKeyGeneratePair 、 SecItemCopyMatching C APIを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 ]
} ( ) )その場合、 Configオブジェクトの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
}署名時にlacontextオブジェクトを渡すこともできます
do {
let digest = " some text to encrypt " . data ( using : . utf8 ) !
let encrypted = try KeyPair . manager . encrypt ( digest , hash : . sha256 )
} catch {
// handle error
}また、公開キーを使用して、別のデバイス/OS/プラットフォームで暗号化することもできます。安全なエンクレーブが理解している形式で暗号化する方法に関するすべての詳細を知りたい場合は、@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
}また、復号化するときに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 Curve Cryptography、ECDSA、ECDH、ASN.1 ksecattrtokenidsecureenclave、lacontext、localauthentication、faceid、face id、touchid、touch id、application password、device pin、devicepin
TrailOfbitsは、しばらく前にObjective-Cコードを公開しました。 TidasとSecureEnclaveCryptoを共有してくれてありがとう。彼らはまた、他の最も興味深いプロジェクトをいくつか持っています。それらをチェックしてください!
彼は、適切なDer X.509形式で公開鍵をエクスポートすることに関して、SOMを非常に貴重な洞察を共有しました。
SHA256クラス(元々 SHA2.swift )は、Marcin Krzy’anowskiによる貴重なCryptoswiftライブラリにあります。クラスは、このプロジェクトで必要なものに対して最小限に抑えるために、クラスが大幅に変更されています。
シミュレータにタッチID /デバイスピンでプロンプトが表示されないのはなぜですか?
シミュレーターは安全なエンクレーブを所有していないため、アクセスしようとすると、エラーが発生します。
fallbackToKeychainIfSecureEnclaveIsNotAvailablefortrueを設定すると、秘密キーはシミュレーターのキーチェーンに保存され、シミュレータでアプリケーションを簡単にテストできます。
どこでもっと知ることができますか?
WWDC 2015の一般的なセキュリティに関するこのビデオをご覧になるか、ここをクリックして、安全なエンクレーブに関するセクションのすぐにスキップしてください。
なぜそれが列挙に包まれているのですか?
必要なファイルをXcodeにドラッグアンドドロップし、CarthageやCocoapodsなどの依存関係マネージャーを同時にサポートしようとしています。あなたがより良いアイデアを持っているか、この決定に同意しないならば、私は喜んで代替案について話し合います:)
私たちはしますか?この図書館についてのあなたの意見を聞くために。あなたが好きかしないか。改善したいものがある場合は、問題を提出してください。 Twitterや他の場所で@hfossliとして連絡できます。 ?