ios, alamofire5: perlu yang setara dengan curl --key foo.key --cert foo, pem --location --request GET 'https: //bar.baz/foo "

Sep 11 2020

Saya memiliki kunci pribadi selain kunci publik untuk menyematkan sertifikat.

Bagaimana mengotentikasi dengan ke server?

$ file *
foo.der:         data
foo.private.der: data

diturunkan dengan openssl from

foo.key: PEM RSA private key
foo.pem: PEM certificate

yang saya butuhkan adalah alamofire yang setara dengan ini:

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!"

bekerja

$ curl --cert ./client.pem --location --request GET 'https: // someurl / v1 / welcome /' curl: (58) tidak dapat menyetel file kunci pribadi: './client.pem' ketik PEM

tidak

Jadi saran untuk menggunakan sertifikat itu sendiri tanpa kunci privat tidak akan berhasil.

Apakah kita berurusan dengan penyematan sertifikat di sini atau mengingat adanya kunci pribadi, ini adalah hal lain yang terjadi di sini ???

Jawaban

2 gcharita Sep 14 2020 at 08:32

Anda dapat membuat ServerTrustManagerpassing sebagai parameter evaluator Anda per nama host. Untuk penggunaan pin kunci publik PublicKeysTrustEvaluatorseperti ini:

let evaluators: [String : ServerTrustEvaluating] = [
    "your.host.com": PublicKeysTrustEvaluator(performDefaultValidation: false, validateHost: false)
]
let serverTrustManager = ServerTrustManager(evaluators: evaluators)

Untuk penyematan sertifikat, gunakan PinnedCertificatesTrustEvaluatorseperti ini:

let evaluators: [String : ServerTrustEvaluating] = [
    "your.host.com": PinnedCertificatesTrustEvaluator(
        acceptSelfSignedCertificates: true,
        performDefaultValidation: false,
        validateHost: false
    )
]
let serverTrustManager = ServerTrustManager(evaluators: evaluators)

Kedua metode tersebut memerlukan sertifikat Anda untuk disertakan dalam bundel Anda sebagai .ceratau .derfile.

Setelah membuat ServerTrustManagerpass Anda ke sebuah Sessioninstance dan gunakan ini untuk permintaan Anda:

let session = Session(serverTrustManager: serverTrustManager)

Jika Anda ingin memiliki logika yang lebih kompleks tentang bagaimana Anda memverifikasi server Anda atau Anda harus menggunakan wildcard di domain Anda, Anda harus membuat subkelas ServerTrustManagerdan mengganti serverTrustEvaluator(forHost:)fungsi:

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. mengemas kunci pribadi dan publik ke dalam wadah p12 dengan openssl
  2. Ini adalah kunci Alamofire tanpa evaluasi dan dengan mengirimkan sertifikat klien

membuat instance PKCS512 () dan membuat URLCredential menggunakan itu (kode di tautan di atas) di alamofire semua yang Anda butuhkan dari tautan di atas adalah kelas PKCS12 dan ekstensi 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. memasukkan kredensial tersebut untuk mengautentikasi (dengan: urlCredential) per sesi yang hilangDidReceiveChallenge di delegasi Alamofire 5

dan itu dia.

Kata sandi hardcode ke konstruktor p12 sangat jelek. Eww Kunci apa yang saya kira adalah base64 memanggang di p12 menjadi kode daripada menjadikannya sebagai file yang rentan terhadap ipa patcher attach.