ios、alamofire5:curl --key foo.key --cert foo、pem --location --request GET'https://bar.baz/foo "と同等のものが必要

Sep 11 2020

証明書を固定するための公開鍵に加えて、秘密鍵を持っています。

サーバーに対してどのように認証しますか?

$ 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

ではない

したがって、秘密鍵なしで証明書自体を使用するという提案は機能しません。

ここで証明書のピン留めを扱っているのですか、それとも秘密鍵の存在を考えると、これは別のことです。

回答

2 gcharita Sep 14 2020 at 08:32

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)
    }
}
2 AntonTropashko Sep 14 2020 at 12:04
  1. opensslを使用して秘密鍵と公開鍵をp12コンテナにパックしました
  2. これは、評価なしでクライアント証明書を送信する際の重要な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 }
    }
}
  1. Alamofire 5デリゲートのMissing sessionDidReceiveChallengeごとに認証するためにその資格情報をフィードしました(with:urlCredential)

それだけです。

パスワードをp12コンストラクターにハードコーディングするのは非常に醜いものでした。Eww私が推測する重要な点は、ipaパッチが添付されやすいファイルとしてではなく、p12でbase64をコードにベイクすることです。