简体   繁体   中英

Trust a self-signed certificate for a HTTPS connection

I am creating an iOS app using Swift which connects with a server. This is the code I use to upload an image:

public class SendImages: NSObject,NSURLConnectionDelegate {

    var user = UserInfo?()
    var url = String?()
    var urladditional = String?()
    var sendImages: NSURLConnection = NSURLConnection()
    var my_data:NSMutableData? = nil
    var statusCode: NSInteger? = nil
    public var delegate = SendImagesInterface?()

    init(url: String) {       
        self.url = url
    }

    public func send(images_to_data: NSMutableArray ,user: UserInfo) {

        var error : NSError?
        var data_to_send : NSData = NSJSONSerialization.dataWithJSONObject(jsontoSend,
            options: NSJSONWritingOptions(0), error: &error)!

        var completeURL: AnyObject? = AnyObject?()
        completeURL = NSURL(string: (self.url)!+(self.urladditional)!)

        let cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
        var request = NSMutableURLRequest(URL: completeURL as NSURL, cachePolicy: cachePolicy, timeoutInterval: 30.0)
        request.HTTPMethod = "POST"
        request.HTTPBody = data_to_send

        sendImages = NSURLConnection(request: request, delegate: self)!
        self.my_data = NSMutableData()
    }

    func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
        println("Error to connect with URL")
        self.my_data = nil
    }

    func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
        println("Receiving data")
        self.my_data!.appendData(data)
    }

    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {            
        println("Receiving response headers")
        var httpResponse = response as NSHTTPURLResponse
        statusCode = httpResponse.statusCode
    }

    func connectionDidFinishLoading(connection: NSURLConnection!){
        println("Conexion finished")
    }
}

Now for added security I want to use a HTTPS connections. How can I achieve this? I have a certificate in the .der format, which I think is what iOS uses.

What you need to do to make this work is respond with a NSURLCredential to the URLSession(_:didReceiveChallenge:completionHandler:) delegate call.

The basic steps are:

  1. Load the certificate from your bundle into a CFDataRef .
  2. Extract the identity from the certificate required for the NSURLCredential .
  3. Use the extracted identity with SecIdentityCopyCertificate to create a SecCertificateRef .
  4. Create the NSURLCredential with init(identity:certificates:persistence:)

This example shows how to extract the identity and trust of a certificate loaded from a bundle:

struct IdentityAndTrust {        
    var identity:SecIdentityRef
    var trust:SecTrustRef
}

func extractIdentity(certData:NSData, certPassword:String) -> IdentityAndTrust {

    var identityAndTrust:IdentityAndTrust!
    var securityError:OSStatus = errSecSuccess;

    var items:Unmanaged<CFArray>?
    var certOptions:CFDictionary = [ kSecImportExportPassphrase.takeRetainedValue() as String: certPassword ];
    securityError = SecPKCS12Import(certData, certOptions, &items);

    if securityError == 0 {

        let certItems:CFArray = items?.takeUnretainedValue() as CFArray!;
        let certItemsArray:Array = certItems as Array
        let dict:AnyObject? = certItemsArray.first;

        if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {
            let identityPointer:AnyObject? = certEntry["identity"];
            let secIdentityRef:SecIdentityRef = identityPointer as SecIdentityRef!;

            let trustPointer:AnyObject? = certEntry["trust"];
            let trustRef:SecTrustRef = trustPointer as SecTrustRef;

            identityAndTrust = IdentityAndTrust(identity: secIdentityRef, trust: trustRef);
        }
    } 

    return identityAndTrust;
}

There are a few things you have to keep in mind, first and foremost certificates are able to expire. You should be aware that at one point you may have to change the certificate so prepare for that eventuality from the start. Besides you should prefer NSURLSession over NSURLConnection because with every release more and more methods are deprecated.

You can find a few examples of how to deal with certificates and trust here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM