ios、alamofire5:curl --key foo.key --cert foo、pem --location --request GET'https://bar.baz/foo "と同等のものが必要
証明書を固定するための公開鍵に加えて、秘密鍵を持っています。
サーバーに対してどのように認証しますか?
$ file *
foo.der: data
foo.private.der: data
からopensslで派生
foo.key: PEM RSA private key
foo.pem: PEM certificate
私が必要としているのは、これに相当するalamofireです。
curl --key foo.key --cert foo.pem --location --request GET'https:// somhostofmine / v1 / welcome / '
$ curl --key ./client_key.pem --cert ./client.pem --location --request GET'https:// someurl '"Hello wold!"
動作します
$ curl --cert ./client.pem --location --request GET'https:// someurl / v1 / welcome / 'curl:(58)秘密鍵ファイルを設定できません:' ./ client.pem 'タイプPEM
ではない
したがって、秘密鍵なしで証明書自体を使用するという提案は機能しません。
ここで証明書のピン留めを扱っているのですか、それとも秘密鍵の存在を考えると、これは別のことです。
回答
ServerTrustManagerホスト名ごとに評価者をパラメータとして渡すことを作成できます。公開鍵ピンニングの場合PublicKeysTrustEvaluatorは、次のように使用します。
let evaluators: [String : ServerTrustEvaluating] = [
"your.host.com": PublicKeysTrustEvaluator(performDefaultValidation: false, validateHost: false)
]
let serverTrustManager = ServerTrustManager(evaluators: evaluators)
証明書ピンニングの場合PinnedCertificatesTrustEvaluatorは、次のように使用します。
let evaluators: [String : ServerTrustEvaluating] = [
"your.host.com": PinnedCertificatesTrustEvaluator(
acceptSelfSignedCertificates: true,
performDefaultValidation: false,
validateHost: false
)
]
let serverTrustManager = ServerTrustManager(evaluators: evaluators)
どちらの方法でも、証明書をバンドル.cerまたは.derファイルに含める必要があります。
ServerTrustManagerパスを作成した後、それをSessionインスタンスに渡し、これをリクエストに使用します。
let session = Session(serverTrustManager: serverTrustManager)
サーバーの検証方法についてより複雑なロジックが必要な場合、またはドメインでワイルドカードを使用する必要がある場合は、関数をサブクラス化ServerTrustManagerしてオーバーライドserverTrustEvaluator(forHost:)する必要があります。
class MyServerTrustManager: ServerTrustManager {
init() {
super.init(evaluators: [:])
}
override func serverTrustEvaluator(forHost host: String) throws -> ServerTrustEvaluating? {
guard host.hasSuffix(".host.com") else {
return try super.serverTrustEvaluator(forHost: host)
}
return PublicKeysTrustEvaluator(performDefaultValidation: false, validateHost: false)
}
}
- opensslを使用して秘密鍵と公開鍵をp12コンテナにパックしました
- これは、評価なしでクライアント証明書を送信する際の重要なAlamofireでした
PKCS512()インスタンスを作成し、それを使用して(上記のリンクのコード)alamofireでURLCredentialを作成しました。上記のリンクから必要なのは、PKCS12クラスとURLCredential拡張機能だけです。
public class PKCS12 {
let label:String?
let keyID:NSData?
let trust:SecTrust?
let certChain:[SecTrust]?
let identity:SecIdentity?
public init(PKCS12Data:NSData,password:String)
{
let importPasswordOption:NSDictionary = [kSecImportExportPassphrase as NSString:password]
var items : CFArray?
let secError:OSStatus = SecPKCS12Import(PKCS12Data, importPasswordOption, &items)
guard secError == errSecSuccess else {
if secError == errSecAuthFailed {
NSLog("ERROR: SecPKCS12Import returned errSecAuthFailed. Incorrect password?")
}
fatalError("SecPKCS12Import returned an error trying to import PKCS12 data")
}
guard let theItemsCFArray = items else { fatalError() }
let theItemsNSArray:NSArray = theItemsCFArray as NSArray
guard let dictArray = theItemsNSArray as? [[String:AnyObject]] else { fatalError() }
func f<T>(key:CFString) -> T? {
for d in dictArray {
if let v = d[key as String] as? T {
return v
}
}
return nil
}
self.label = f(key: kSecImportItemLabel)
self.keyID = f(key: kSecImportItemKeyID)
self.trust = f(key: kSecImportItemTrust)
self.certChain = f(key: kSecImportItemCertChain)
self.identity = f(key: kSecImportItemIdentity)
}
}
extension URLCredential {
public convenience init?(PKCS12 thePKCS12:PKCS12) {
if let identity = thePKCS12.identity {
self.init(
identity: identity,
certificates: thePKCS12.certChain,
persistence: URLCredential.Persistence.forSession)
}
else { return nil }
}
}
- Alamofire 5デリゲートのMissing sessionDidReceiveChallengeごとに認証するためにその資格情報をフィードしました(with:urlCredential)
それだけです。
パスワードをp12コンストラクターにハードコーディングするのは非常に醜いものでした。Eww私が推測する重要な点は、ipaパッチが添付されやすいファイルとしてではなく、p12でbase64をコードにベイクすることです。