Alamofire 无需评估并发送客户端证书 [英] Alamofire without evaluation and with sending client certificate

查看:42
本文介绍了Alamofire 无需评估并发送客户端证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,我现在对 alamofire 很着迷 :).我想要做的是禁用评估,因为服务器没有有效的 SSL 证书,但我必须通过 https 连接,我必须发送由 OpenSSL 在 IOS 设备上制作的 x509 证书我目前正在使用 alamofire 4,我正在尝试这样做:

Hello i am currently going crazy with alamofire :). What I'm trying to do is to disable evaluation because server has no valid SSL certificate but I have to connect by https and I have to send a x509 certificate made on IOS device by OpenSSL I am currently using alamofire 4 and I was trying to do:

open class CertTrustPolicyManager: ServerTrustPolicyManager {

    open override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
    let policy = ServerTrustPolicy.disableEvaluation;

 //   let policy = ServerTrustPolicy.pinCertificates(certificates: [certificateToPin], validateCertificateChain: true, validateHost: false);

  //  var policy  = ServerTrustPolicy.pinCertificates(certificates: [certificateToPin], validateCertificateChain: false, validateHost: false);

return policy
}
    let trustPolicies = CertTrustPolicyManager(policies: [:])

    let alamofireManager:SessionManager = Alamofire.SessionManager(configuration: configuration, delegate: SessionDelegate(), serverTrustPolicyManager: trustPolicies)

也在努力

var serverTrustPolicy:[String: ServerTrustPolicy] = [
    Router.baseURLString : .pinCertificates(
        certificates: [certificateToPin],
        validateCertificateChain: false,
        validateHost: false)

]


let alamofireManager:SessionManager = Alamofire.SessionManager(configuration: configuration, delegate: SessionDelegate(), serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicy))

第一种方法让策略 = ServerTrustPolicy.disableEvaluation;给了我成功的连接,但后来我无法固定证书(或者我不知道如何)

First approach with let policy = ServerTrustPolicy.disableEvaluation; gave me successful connection but then I'm unable to pin certificate ( or I don't know how)

第二种方法产生,天知道接下来会发生什么:)

second approach produces and god knows whats next :)

2017-05-10 08:37:13.801894+0200 App[10117:1120893] [] nw_coretls_callback_handshake_message_block_invoke_3 tls_handshake_continue: [-9812]
2017-05-10 08:37:13.802 App[10117:1120907] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)

我什至不知道我是否正确发送.

I don't even know if I'm sending it correctly.

有什么建议吗?

编辑这使我的连接良好,但我没有发送证书

 alamofireManager.delegate.sessionDidReceiveChallenge = { session, challenge in
            var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
            var credential: URLCredential?

            if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
                disposition = URLSession.AuthChallengeDisposition.useCredential
                credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
            } else {
                if challenge.previousFailureCount > 0 {
                    disposition = .cancelAuthenticationChallenge
                } else {
                    credential = alamofireManager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)

                    if credential != nil {
                        disposition = .useCredential
                    }
                }
            }

            return (disposition, credential)
        }

干杯

推荐答案

问题自行解决.

现在发送客户端证书的答案也许有人会需要它:)

now the answer for SENDING CLIENT SIDE CERTIFICATE maybe someone will need it :)

我们需要PKCS12来发送证书

We need PKCS12 to send certificate so

import Foundation

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 }
    }
}

我们也需要 x509 来做 PKCS12 我需要动态生成证书,所以有从 C 桥接的代码

we need x509 also to do PKCS12 I was in need of generating certificates dynamically so theres the code bridged from C

-(void) createX509{
    OPENSSL_init();

    NSString *docPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/cert"];
    NSString *docPathKey = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/key"];
    NSString *docPathp12 = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/p12"];


    NSString *dataFile = [NSString stringWithContentsOfFile:docPath
                                                   encoding:NSUTF8StringEncoding
                                                      error:NULL];

    FILE *fp = fopen(docPath.UTF8String, "r");

    if(fp == NULL){
        fp = fopen(docPath.UTF8String, "w+");
        FILE *fpKey = fopen(docPathKey.UTF8String, "w+");

    EVP_PKEY * pkey;
    pkey = EVP_PKEY_new();

    RSA * rsa;
    rsa = RSA_generate_key(
                           2048,   /* number of bits for the key - 2048 is a sensible value */
                           RSA_F4, /* exponent - RSA_F4 is defined as 0x10001L */
                           NULL,   /* callback - can be NULL if we aren't displaying progress */
                           NULL    /* callback argument - not needed in this case */
                           );

    EVP_PKEY_assign_RSA(pkey, rsa);

    X509 * x509;
    x509 = X509_new();

    ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);

    X509_gmtime_adj(X509_get_notBefore(x509), 0);
    X509_gmtime_adj(X509_get_notAfter(x509), 31536000000L);

    X509_set_pubkey(x509, pkey);

    X509_NAME * name;
    name = X509_get_subject_name(x509);

    X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
                               (unsigned char *)"CA", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
                               (unsigned char *)"company", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                               (unsigned char *)"localhost", -1, -1, 0);

    X509_set_issuer_name(x509, name);

    X509_sign(x509, pkey, EVP_sha1());

        [@"" writeToFile:docPath
                   atomically:YES
                     encoding:NSUTF8StringEncoding
                        error:NULL];
        fp = fopen(docPath.UTF8String, "a+");
        PEM_write_X509(
                       fp,   /* write the certificate to the file we've opened */
                       x509 /* our certificate */);
        PEM_write_PrivateKey(fpKey, pkey, NULL, NULL, 0, NULL, NULL);
        fflush(fpKey);
        fclose(fpKey);
        fflush(fp);
        fclose(fp);
        dataFile = [NSString stringWithContentsOfFile:docPath
                                             encoding:NSUTF8StringEncoding
                                                error:NULL];

        OpenSSL_add_all_algorithms();
        OpenSSL_add_all_ciphers();
        OpenSSL_add_all_digests();

        PKCS12* p12;
        p12 = PKCS12_create("password", "login", pkey, x509, NULL, 0,0,0,0,0);

        if(!p12) {
            fprintf(stderr, "Error creating PKCS#12 structure\n");
            ERR_print_errors_fp(stderr);
            exit(1);
        }
        fp = fopen(docPathp12.UTF8String, "w+");

        if (!(fp = fopen(docPathp12.UTF8String, "wb"))) {
            ERR_print_errors_fp(stderr);
            exit(1);
        }
        i2d_PKCS12_fp(fp, p12);
        PKCS12_free(p12);
        fflush(fp);
        fclose(fp);


    }

现在已经制作了 pkcs12 和 x05,所以我们继续快速

The pkcs12 and x05 is now made so we continue in swift

 public let alamofireManager: SessionManager = {
        let obj = OpenSSL();
        obj.createX509()

        var path  = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first;
        var certPEM:String!;
        var keyPEM:String!;
        var certificateToPin:SecCertificate!;
        var pkcs12:PKCS12?;
        do{
            try certPEM = String(contentsOfFile: path! + "/cert").replacingOccurrences(of: "\n", with: "")
            try keyPEM = String(contentsOfFile: path! + "/key").replacingOccurrences(of: "\n", with: "")
            let p12 = NSData(contentsOfFile: path! + "/p12");
             pkcs12 = PKCS12.init(PKCS12Data: p12!, password: "password")

            let docsurl = try! FileManager.default.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)

            let urlAp = docsurl.appendingPathComponent("cert");
            var cert64 = certPEM.replacingOccurrences(of: "-----BEGIN CERTIFICATE-----", with: "")
            cert64 = cert64.replacingOccurrences(of: "-----END CERTIFICATE-----", with: "")
            let certificateData = NSData(base64Encoded: cert64, options: .ignoreUnknownCharacters)
            certificateToPin = SecCertificateCreateWithData(kCFAllocatorMalloc, certificateData!)

            var trust: SecTrust?

            let policy = SecPolicyCreateBasicX509()
            let status = SecTrustCreateWithCertificates(certificateToPin!, policy, &trust)
            let publicKey:SecKey?;
            if status == errSecSuccess {
                publicKey = SecTrustCopyPublicKey(trust!)!;
            }

            let dictionary = SecPolicyCopyProperties(policy)

        }catch{
            print("err")
        }


        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForResource = Request.settings.timeout


        let trustPolicies = CertTrustPolicyManager(policies: [:])


        var serverTrustPolicy:[String: ServerTrustPolicy] = [
            Router.baseURLString : .pinCertificates(
                certificates: [certificateToPin],
                validateCertificateChain: false,
                validateHost: false)
        ]


        var alamofireManager:SessionManager = Alamofire.SessionManager(configuration: configuration, delegate: SessionDelegate(), serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicy))

        alamofireManager.delegate.sessionDidReceiveChallenge = { session, challenge in
            var disposition: URLSession.AuthChallengeDisposition = .useCredential
            var credential: URLCredential?

            if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
                disposition = URLSession.AuthChallengeDisposition.useCredential
                credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)

            } else {
                if challenge.previousFailureCount > 0 {
                    disposition = .cancelAuthenticationChallenge
                } else {
                    credential = alamofireManager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)

                    if credential != nil {
                        disposition = .useCredential
                    }
                }
            }

            let certs = [certificateToPin]
            let persist = URLCredential.Persistence.forSession;

            return (disposition, URLCredential.init(PKCS12: pkcs12!))
        }


        return alamofireManager
    }()

我需要获得证书,可能有些代码没用或写得不好,但它可以工作(我是 IOS 的新手 :)),我也在那里将 PEM 证书转换为 DER,但在这些操作之后我是终于能够与发送客户端建立不安全的连接并使用 Alamofire 创建证书.

There I was in need to get certificates, probably some of code is useless or badly wrote but its working ( I'm new to IOS :) ), I was also converting PEM certificates to DER there but after these operations I was finally able to do insecure connection with sending client side and created certificate with Alamofire.

上面的代码是从各地收集的!

The code above is gathered from everywhere!

干杯

这篇关于Alamofire 无需评估并发送客户端证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆