iOS development HTTPS implementation of trusted SSL and self-signed certificates

Source: Internet
Author: User
Tags ssl certificate

iOS development HTTPS implementation of trusted SSL and self-signed certificates

Transferred from: http://www.jianshu.com/p/6b9c8bd5005a/comments/5539345

(Included for your own study)

words 1566 read 5025 comments like First, analyze what HTTPS is and what HTTPS means to iOS developers. HTTPS and SSL/TSL
    • What is SSL?

SSL (secure Sockets layer), because the HTTP protocol used on the internet is plaintext, there are many drawbacks, such as the transmission of content will be peeping (sniffing) and tampering. The purpose of the SSL protocol is to encrypt the network connection at the transport layer.

    • What is TLS?

By the year 1999, SSL has become a de facto standard on the Internet because of its wide application. The IETF standardized SSL in that year. After normalization, the name is changed to TLS (Transport layer Security, Transport Layer secure Protocol). SSL and TLS can be seen as different stages of the same thing

    • HTTPS

Simply put, HTTPS = http + SSL/TLS, or HTTP over SSL or HTTP over TLS, which is the origin of the following S.

HTTPS and HTTP similarities and differences: HTTP and HTTPS use a completely different way of connection, with the same port, the former is 80, the latter is 443. The HTTP connection is simple and stateless; The HTTPS protocol is a network protocol built by the SSL+HTTP protocol for encrypted transmission and authentication, which is more secure than the HTTP protocol.

At the WWDC 2016 developer conference, Apple announced a deadline: The app Transport security feature must be enabled for all apps in the App Store by January 1, 2017. APP Transport Security (ATS) is a privacy protection feature introduced by Apple in iOS 9, which blocks plaintext HTTP resources from loading, and connections must be more secure HTTPS. Apple currently allows developers to temporarily shut down ATS and continue to use HTTP connections, but the use of ATS must be mandatory for all official stores by the end of the year.

So for iOS developers, the issue of HTTPS requests needs to be resolved as early as possible.

Send HTTPS requests to trust SSL and self-signed certificates in three scenarios

1. If your app server is SLL issued CA, you can use the system method to directly implement the trust SSL certificate, about Apple's requirements for SSL certificate refer to: Apple Official document Certkeytrustprogguide

This way does not need to introduce a CA file in the bundle, can be handed over to the system to determine whether the server-side certificate is SSL certificate, the verification process does not require us to implement the specific.

Example code:

nsurl *url = [NSURL URLWithString : URLString]; nsurlrequest *request = [[nsurlrequest alloc] InitWithURL: URL cachepolicy:nsurlrequestreloadignoringlocalcachedata TimeoutInterval:10]; //Create a sync connection nserror *error = NIL; Span class= "hljs-built_in" >nsdata *receiveddata = [nsurlconnection Sendsynchronousrequest:request returningresponse:nil error:&error]; nsstring *receivedinfo = [[nsstring alloc] InitWithData: Receiveddata encoding:nsutf8stringencoding];        

Of course, if you need to trust both the SSL and the self-signed certificates, you will need to implement the CA validation in your code, which is mentioned later.

2. afnetworking-based SSL specific server certificate trust processing, overriding afnetworking Customsecuritypolicy method, here I created a HttpRequest class, respectively, the Get and post methods are encapsulated, Take the Get method as an example:

+ (void) Get: (NSString *) URL params: (Nsdictionary *) Params success: (void (^) (ID)) Success failure: (void (^) (Nserror *)) Failure {1. Get request Manager Afhttprequestoperationmanager *mgr = [Afhttprequestoperationmanager manager];//2. Affirms that the result of the return is text/html type Mgr.responseserializer = [ Afhttpresponseserializer Serializer]; //3. Set time-out to 10s Mgr.requestserializer .timeoutinterval = 10; //plus this line of code, HTTPS SSL authentication. if (OPENHTTPSSSL) {[Mgr Setsecuritypolicy:[self Customsecuritypolicy]]; } //4. Send GET Request [Mgr Get:url parameters:params success:^ (afhttprequestoperation *operation, id responseobj) {if (Success) {success (Responseobj)}} failure:^ (Afhttprequestoperation *operation, Span class= "hljs-built_in" >nserror *error) {if (Error) {failure (error);}}];}   
+ (afsecuritypolicy*) Customsecuritypolicy {/Import Certificates FirstNSString *cerpath = [[NSBundle Mainbundle] pathforresource:certificate ofType:@ "CER"];Path to the certificateNSData *certdata = [NSData Datawithcontentsoffile:cerpath];Afsslpinningmodecertificate using certificate validation mode afsecuritypolicy *securitypolicy = [Afsecuritypolicy policywithpinningmode: Afsslpinningmodecertificate];//allowinvalidcertificates whether to allow invalid certificates (that is, self-built certificates), default to No // If you need to validate your self-built certificate, you need to set it to Yes Securitypolicy.allowinvalidcertificates = yes; //validatesdomainname need to verify the domain name, default is yes; //if the domain name of the certificate does not match the domain name you requested , you need to set the item to no, and if it is set to No, that is, the server uses a certificate issued by another trusted authority, it can also establish a connection, this is very dangerous, it is recommended to open. //to No, mainly used in this case: the client is requesting a subdomain, and the certificate is another domain name. Because the domain name on the SSL certificate is independent, if the domain name registered on the certificate is www.google.com, then mail.google.com cannot be verified; Of course, the rich can register the wildcard name *.google.com, but this is still relatively expensive. //if set to No, it is recommended that you add the corresponding domain name of the check logic. Securitypolicy.validatesdomainname = NO; securityPolicy< Span class= "hljs-variable" >.pinnedcertificates = @[certdata]; return securitypolicy;}           

The Cerpath is the certificate path in the app bundle, certificate is a macro for the certificate name, only the CER format is supported, and the related configuration of securitypolicy is particularly important. Please read the Customsecuritypolicy method carefully and set its properties according to the actual situation.

In this way, it is possible to use the HTTPS protocol to access a particular server on a afnetworking basis, but the CA file of the root certificate cannot be trusted, so there is a risk that it may fail to read the array of certificates in Pinnedcertificates if the certificate does not conform, The Certdata will be nil.

3. Change the system method to send an asynchronous nsurlconnection request.

-(void) getDataWithURLRequest { //connection nsstring *urlstr = @    "https://developer.apple.com/cn/"; nsurl *url = [nsurl urlwithstring:urlstr]; nsmutableurlrequest *request = [nsmutableurlrequest RequestWithURL:url Cachepolicy:nsurlrequestuseprotocolcachepolicy timeoutinterval: 10]; nsurlconnection *connection = [[NSURLConnection alloc] Initwithrequest:request delegate:self]; [Connection start];}               

The focus is on handling Nsurlconnection's Didreceiveauthenticationchallenge proxy method, validating the CA file, and establishing a trust connection.

- (BOOL) Connection: (Nsurlconnection *) connection canauthenticateagainstprotectionspace: (Nsurlprotectionspace *) Protectionspace {return [Protectionspace. Authenticationmethod isequaltostring:Nsurlauthenticationmethodservertrust];} - (void) Connection: (Nsurlconnection *) connection Didreceiveauthenticationchallenge: (Nsurlauthenticationchallenge *) Challenge {/*//directly Verify that the server is authenticated (Servertrust), which directly ignores certificate authentication, directly establishes a connection, but does not filter other URL connections, which can be understood as a compromise approach that is not actually secure and therefore not recommended. Sectrustref servertrust = [[Challenge Protectionspace] servertrust]; return [[Challenge Sender] Usecredential: [Nsurlcredential Credentialfortrust:servertrust] Forauthenticationchallenge:challenge]; */if ([[[[Challenge Protectionspace] Authenticationmethod] isequaltostring:Nsurlauthenticationmethodservertrust]) {do {sectrustref servertrust = [[Challenge Protectionspace] servertrust];Nscassert (Servertrust! =Nil@ "Servertrust is nil");IfNil = = Servertrust)Break/* Failed *//** * Import multiple CA certificates (certification authority, support SSL certificate and self-signed CA) */NSString *cerpath = [[NSBundle Mainbundle] Pathforresource:@ "Cloudwin" OfType:@ "CER"];Self-signed certificatensdata* CaCert = [NSData Datawithcontentsoffile:cerpath];NSString *cerpath2 = [[NSBundle Mainbundle] Pathforresource:@ "Apple" OfType:@ "CER"];SSL CertificateNSData * CaCert2 = [NSData Datawithcontentsoffile:cerpath2];Nscassert (CaCert! =Nil@ "CaCert is nil");IfNil = = CaCert)Break/* Failed */Nscassert (CaCert2! =Nil@ "CaCert2 is nil");if (Nil = = CaCert2) {Break } seccertificateref caref = Seccertificatecreatewithdata (NULL, (__bridgeCFDATAREF) CaCert);Nscassert (Caref! =Nil@ "Caref is nil");IfNil = = Caref)Break/* Failed */seccertificateref CaRef2 = Seccertificatecreatewithdata (NULL, (__bridgeCFDATAREF) caCert2);Nscassert (CaRef2! =Nil@ "CaRef2 is nil");IfNil = = CaRef2)Break/* Failed */Nsarray *caarray = @[(__bridgeID) (CAREF), (__bridgeID) (CAREF2)];Nscassert (Caarray! =Nil@ "Caarray is nil");IfNil = = Caarray)Break/* Failed */osstatus status = Sectrustsetanchorcertificates (Servertrust, (__bridgeCFARRAYREF) Caarray);Nscassert (errsecsuccess = = Status,@ "Sectrustsetanchorcertificates failed");if (! ( Errsecsuccess = = status))Break/* Failed */sectrustresulttype result =-1; Status = Sectrustevaluate (Servertrust, &result);if (! ( Errsecsuccess = = status))Break/* Failed */NSLog (@ "stutas:%d", (int) status);NSLog (@ "Result:%d", result);BOOL Allowconnect = (Result = = ksectrustresultunspecified) | | (Result = = Ksectrustresultproceed);if (allowconnect) {NSLog (@ "Success"); }else {NSLog (@ "error"); }/* https://developer.apple.com/library/ios/technotes/tn2232/_index.html *//* https://developer.apple.com/library/mac/qa/qa1360/_index.html *//* Ksectrustresultunspecified and Ksectrustresultproceed are success */if (! Allowconnect) {Break/* Failed */}#if 0/* Treat Ksectrustresultconfirm and Ksectrustresultrecoverabletrustfailure as success *//* since the user would likely tap-through to see the dancing bunnies * * if (result = = Ksectrustresultdeny | | result = = Ksectrustresultfataltrustfailure | | result = = Ksectrustresultothererror) break; /* Failed to trust cert (good in the case) */ #endif //the only good exit point return [[Challenge Sender] Usecredential: [ Span class= "hljs-built_in" >nsurlcredential Credentialfortrust:servertrust] forauthenticationchallenge:challenge]; } while (0);} //Bad Dog return [[Challenge Sender] Cancelauthenticationchallenge:challenge];}            

The key here is the value of the result parameter, judging by the official document's description (result = = ksectrustresultunspecified) | | (Result = = Ksectrustresultproceed) value, if 1, the site's CA is successfully trusted by the app, can establish a data connection, which means that all the individual server certificates issued by the CA are trusted, and access to any other sites that are not trusted will fail to connect. The CA file can be either SLL or self-signed.

Other proxy methods implemented by Nsurlconnection

#pragma mark-the asynchronous proxy method for connect-(void) Connection: (Nsurlconnection *) connection didreceiveresponse: (Nsurlresponse *) Response {NSLog (@ "request is answered"); _mdata = [[Nsmutabledata Alloc]init];} -(void) Connection: (Nsurlconnection *) connection didreceivedata: (nonnullNSData *) Data {NSLog (@ "Start returning data fragment"); [_mdata Appenddata:data];} -(void) Connectiondidfinishloading: (Nsurlconnection *) Connection {NSLog (@ "link complete");//can parse data here nsstring *receiveinfo = [ nsjsonserialization jsonobjectwithdata:self.mdata options:nsjsonreadingallowfragments Error: nil]; nslog (@ "received data:\\\\n%@", self.mdata); nslog (@ "received info:\\\\n%@", Receiveinfo);} //link error-(void) connection: (nserror *) Error { nslog (@ "error-%@", error);}      

At this point, the issue of the HTTPS trust certificate is resolved, not only in response to Apple's mandatory use of ATS, but also for the actual production environment security considerations, HTTPS is the future trend, we recommend early support.

iOS development HTTPS implementation of trusted SSL and self-signed certificates

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.