iOS基于AFNetworking使用自签名证书实现HTTPS请求

二:HTTPS加密方式

对称加密只有一个密钥,加密和解密都用这个密钥;

非对称加密有公钥和私钥,私钥加密后的内容只有公钥才能解密,公钥加密的内容只有私钥才能解密。公钥加密的另一用途是身份验证:用私钥加密的信息,可以用公钥对其解密,接收者由此可知这条信息确实来自于拥有私钥的某人。私钥加密的过程即数字签名

为了提高安全性,我们常用的做法是使用对称加密的手段加密数据。可是只使用对称加密的话,双方通信的开始总会以明文的方式传输密钥。那么从一开始这个密钥就泄露了,谈不上什么安全。所以 TLS/SSL 在握手的阶段,结合非对称加密的手段,保证只有通信双方才知道对称加密的密钥。大概的流程如下:下图同时也是单向认证的原理图。

所以,HTTPS 实现传输安全的关键是:在 TLS/SSL 握手阶段保证仅有通信双方得到 Session Key!

单向认证:认证服务器-服务器给客户端公钥,私钥只有服务器有。只有服务器可以解密。

三、单向认证

Https在建立Socket连接之前,需要进行握手,具体过程如下:

1  客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。

2  服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,

3  客户端使用服务端返回的信息验证服务器的合法性,包括:

◦          证书是否过期

◦          发型服务器证书的CA是否可靠

◦          返回的公钥是否能正确解开返回证书中的数字签名-也就是使用返回的公钥解开证书中用私钥-可知这条信息确实来自于拥有私钥的某人。私钥加密的过程即数字签名

◦          服务器证书上的域名是否和服务器的实际域名相匹配

4  验证通过后,将继续进行通信,否则,终止通信

5  客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择

6  服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。

7  服务器将选择好的加密方案通过明文方式返回给客户端

8  客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器

9  服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。

10 在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。

四、双向认证

双向认证和单向认证原理基本差不多,只是除了客户端需要认证服务端以外,增加了服务端对客户端的认证,具体过程如下:

1  客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。

2  服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书

3  客户端使用服务端返回的信息验证服务器的合法性,包括:

◦          证书是否过期

◦          发型服务器证书的CA是否可靠

◦          返回的公钥是否能正确解开返回证书中的数字签名

◦          服务器证书上的域名是否和服务器的实际域名相匹配

4  验证通过后,将继续进行通信,否则,终止通信

5  服务端要求客户端发送客户端的证书,客户端会将自己的证书发送至服务端

6  验证客户端的证书,通过验证后,会获得客户端的公钥

7  客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择

8  服务器端在客户端提供的加密方案中选择加密程度最高的加密方式

9  将加密方案通过使用之前获取到的公钥进行加密,返回给客户端

10 客户端收到服务端返回的加密方案密文后,使用自己的私钥进行解密,获取具体加密方式,而后,产生该加密方式的随机码,用作加密过程中的密钥,使用之前从服务端证书中获取到的公钥进行加密后,发送给服务端

服务端收到客户端发送的消息后,使用自己的私钥进行解密,获取对称加密的密钥,在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。

若干重要验证说明:

1.        客户端验证服务器的Certificate消息。主要验证内容为:

(1).    服务器证书使用日期是否有效。

(2).    发行服务器证书的CA是否可靠。

(3).    发行者的公钥能否解开服务器证书上的“发行者数字签名”。

(4).    服务器证书上的名称(如域名)是否和服务器实际名称匹配等(PHP中可以选择是否验证该选项)。

(Tenfy: 这里可以看出,客户端验证服务的时候,只需要验证对应服务器证书的有效性即可,无需验证对应服务器是否拥有跟该证书一致的私钥)

 

 

2.        服务器验证客户端的CertificateVerify消息。主要验证内容为:

(1).    用客户端公钥能否解开客户端私钥加密的消息。

(Tenfy:服务器验证客户端时候,还需要验证是否拥有跟证书对应的私钥)

 

3.        服务器验证客户端的ClientCertificate消息。主要验证内容为:

(1).    客户的证书使用日期是否有效。

(2).    为客户提供证书的CA 是否可靠。

(3).    发行CA 的公钥能否正确解开客户证书的发行CA的数字签名。

(4).    检查客户的证书是否在证书废止列表(CRL)中。

五.CA证书

CA证书是经过认证的数字证书)是一个用于互联网通讯中认证身份的工具,由权威机构——CA机构(Certificate Authority)发行。CA 是一些非常权威的专门用于认证一个网站合法性的组织。服务商可以向他们申请一个证书,使得他们建立安全连接时可以带上 CA 的签名。而 CA 的安全性由操作系统或浏览器来认证。你的 Windows、Mac、Linux、Chrome、Safari 等会在安装时带上一个他们认为安全的 CA 证书列表。如果和你建立安全连接的人带着这些人的签名,那么认为这个安全连接是安全的,没有遭到中间人攻击。

所以通过 对称加密 + 非对称加密 + CA认证 这三个技术混合在一起,才使得 HTTP 的后面加上了一个 S —— Security。实际上 HTTPS 的协议比我这里描述的更复杂一些,我这里说的主要是基本的实现原理。因为其中任何一环稍有闪失,就会使得整个加密都将变得不安全。这也是为什么 HTTPS 的加密协议从SSL 1.0 升级到 SSL 3.0 再被 TLS 1.0 现在被 TLS 1.2 取代,其背后都是一环环细节上的修改,以防任何地方的闪失。

六.在AFNetworking设置HTTPS单向认证。

NSString *myUrl=@"https://192.168.18.83:9443/testweb/test?action=3";

AFHTTPSessionManager*manager = [AFHTTPSessionManager manager];

    //    设置超时时间

    manager.requestSerializer.timeoutInterval = 30.f;

    [manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];

    [manager.requestSerializer setValue:@"Content-Type" forHTTPHeaderField:@"application/json;charset=utf-8"];

//设置安全政策

//AFSecurityPolicy:=将固定的SSL证书添加到您的应用程序可以帮助防止中间人攻击和其他漏洞。或财务信息处理敏感的客户数据的应用程序被强烈鼓励所有通信路由在一个HTTPS和SSL连接固定配置和启用

    //校验证书的方式

    AFSecurityPolicy*securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

    /**AFSSLPinningModeCertificate=除了公钥外,其他内容也要一致才能通过验证---必须有服务器的证书才可以通过认证

     **AFSSLPinningModePublicKey=只验证公钥部分,只要公钥部分一致就验证通过---必须有服务器的证书才可以通过认证;也就是即使服务器证书有所变动,只要公钥不变,就能通过认证。

     **AFSSLPinningModeNone=不做任何验证,只要服务器返回了证书就通过-,也就是你不必将认证证书跟你的APP一起打包;

     */

    //tomcat1(1)-服务器的证书

    NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];

    NSData *certData = [NSData dataWithContentsOfFile:cerPath];

    NSSet  *dataSet = [NSSet setWithArray:@[certData]];

   

    //是否信任服务器无效或过期的SSL证书。默认为“不”---这个参数是校验证书过期+是否是CA认证有效的();-20170427;

    //经测试:设置为“NO”自签名的证书认证失败,百度等第三方的证书认证成功!-系统在验证到根证书时,发现它是自签名、不可信的。

    [securityPolicy setAllowInvalidCertificates:YES];

   

    [securityPolicy setPinnedCertificates:dataSet];

   

    //是否验证域名证书的CN字段。默认为“是”----------------------测试这里改为NO;

    [securityPolicy setValidatesDomainName:YES];

 

[manager setSecurityPolicy: securityPolicy];

[manager POST: myUrl parameters:nil progress:nil success:success failure:failure];

七.单向认证总结:

1.iOS中证书是否有效的标准:信任链中如果只含有 有效证书并且以“可信锚点(trusted auchor)”结尾,那么这个证书就被称为是有效的。

2.可信任锚点:指系统隐式信任的证书,也就是系统中CA根证书。苹果文档:不要信任隐士的自签名证书,如果要信任需要自己的签名证书添加到证书信任列表中。不过我们可以在验证证书链时,可以设置自定义的证书作为可信任的锚点。也可通过认证。[securityPolicy setAllowInvalidCertificates:NO];设置为NO时:检查证书是否有效,自签名证书会是无效的。百度等CA认证的是有效的证书。

3.如果要验证自签名证书的域名,验证证书不能使用“AFSSLPinningModeNone”:Inorder to validate a domain name for self signed certificates, you MUST usepinning.

4.在AFNetworking嵌入开发,CA证书:系统会自动查找需要匹配的服务器证书。也就是[securityPolicy setPinnedCertificates:dataSet];这个方法可以不用添加

八.设置自定义的证书作为可信任的锚点:

[manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) {

        NSLog(@"setSessionDidBecomeInvalidBlock");

    }];

    __weak typeof(manager)weakManager = manager;

   

    // 该方法的作用就是处理服务器返回的证书, 需要在该方法中告诉系统是否需要安装服务器返回的证书

    // NSURLAuthenticationChallenge : 授权质问- challenge,也就是质询

    //+ 受保护空间

    //+ 服务器返回的证书类型

    //验证证书

    [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {

       

        //第一个参数:challenge 代表如何处理证书

        //第二个参数: NSURLCredential 代表需要处理哪个证书

       

        //// 如果使用默认的处置方式,那么 credential(凭证) 就会被忽略

        NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;

       

        __autoreleasing NSURLCredential *credential =nil;

        NSLog(@"authenticationMethod=%@",challenge.protectionSpace.authenticationMethod);

       

        //判断服务器返回的证书是否是服务器信任的

        // 1.从服务器返回的受保护空间中拿到证书的类型

        // 2.判断服务器返回的证书是否是服务器信任的

        //如果这个值是 NSURLAuthenticationMethodServerTrust 的话,我们就可以插手 TLS 握手中“验证数字证书有效性”这一步。

        if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

            //调用自定义的验证过程

            if ([selfmyCustomValidation:challenge]) {

                    credential =[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

                    if (credential){

                        disposition= NSURLSessionAuthChallengeUseCredential;

                    }

            } else {

                    //无效的话,取消

                disposition =NSURLSessionAuthChallengeCancelAuthenticationChallenge;

            }

           

        *_credential = credential;

        return disposition;

    }];

九:在AFNetworking设置HTTPS双向认证。

NSString *myUrl=@"https://192.168.18.3/testweb/test";

AFHTTPSessionManager*manager = [AFHTTPSessionManager manager];

    //    设置超时时间

    [manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];

    manager.requestSerializer.timeoutInterval = 30.f;

    [manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];

    [manager.requestSerializer setValue:@"Content-Type" forHTTPHeaderField:@"application/json; charset=utf-8"];

   

    //设置安全政策

    [manager setSecurityPolicy:[self customSecurityPolicy]];

   

    //校验证书=验证证书;

    [self checkCredential:manager];

NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];

    NSString *jsonString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

    [manager POST:urlString parameters:jsonString progress:uploadProgress success:success failure:failure];

 

 

 

//校验服务器-证书;

- (AFSecurityPolicy*)customSecurityPolicy {

    AFSecurityPolicy*securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];//AFSSLPinningModeCertificate-校验证书的方式;

    /**AFSSLPinningModeCertificate=除了公钥外,其他内容也要一致才能通过验证---必须有服务器的证书才可以通过认证

     **AFSSLPinningModePublicKey=只验证公钥部分,只要公钥部分一致就验证通过---必须有服务器的证书才可以通过认证;也就是即使服务器证书有所变动,只要公钥不变,就能通过认证。

     **AFSSLPinningModeNone=不做任何验证,只要服务器返回了证书就通过-,也就是你不必将认证证书跟你的APP一起打包;

     */

    //tomcat1(1)-服务器的证书

    NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];

    NSData *certData = [NSData dataWithContentsOfFile:cerPath];

    NSSet  *dataSet = [NSSet setWithArray:@[certData]];

   

    //是否信任服务器无效或过期的SSL证书。默认为“不”---这个参数是校验证书过期+是否是CA认证有效的();-20170427;

    //经测试:设置为“NO”自签名的证书认证失败,百度等第三方的证书认证成功!-系统在验证到根证书时,发现它是自签名、不可信的。

    [securityPolicy setAllowInvalidCertificates:YES];

   

    [securityPolicy setPinnedCertificates:dataSet];

   

    //是否验证域名证书的CN字段。默认为“是”

    [securityPolicy setValidatesDomainName:YES];

    return securityPolicy;

}

//校验证书=验证证书;

- (void)checkCredential:(AFURLSessionManager *)manager

{

    [manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) {

        NSLog(@"setSessionDidBecomeInvalidBlock");

    }];

    __weak typeof(manager)weakManager = manager;

   

    // 该方法的作用就是处理服务器返回的证书, 需要在该方法中告诉系统是否需要安装服务器返回的证书

    // NSURLAuthenticationChallenge : 授权质问

    //+ 受保护空间

    //+ 服务器返回的证书类型

    //验证证书

    [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {

       

        //第一个参数:challenge 代表如何处理证书

        //第二个参数: NSURLCredential 代表需要处理哪个证书

        NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;

        __autoreleasing NSURLCredential *credential =nil;

        NSLog(@"authenticationMethod=%@",challenge.protectionSpace.authenticationMethod);

        //判断是核验客户端证书还是服务器证书--------//判断服务器返回的证书是否是服务器信任的

        // 1.从服务器返回的受保护空间中拿到证书的类型

        // 2.判断服务器返回的证书是否是服务器信任的

        if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {//--客户端验证方法服务器信任

            // 基于客户端的安全策略来决定是否信任该服务器,不信任的话,也就没必要响应挑战

            if([weakManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {

               

                NSLog(@"是服务器信任的证书");

                // 创建挑战证书(注:挑战方式为UseCredential和PerformDefaultHandling都需要新建挑战证书)

                NSLog(@"serverTrust=%@",challenge.protectionSpace.serverTrust);

               

                //创建质询证书-------//创建证书---------

                credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

                // 确定挑战的方式---//确认质询方式

                if (credential) {

                    //证书挑战  设计policy,none,则跑到这里

                    disposition = NSURLSessionAuthChallengeUseCredential;//使用指定的凭据,这可能是零

                   

                } else {

                   

                    disposition = NSURLSessionAuthChallengePerformDefaultHandling;//默认处理挑战——如果没有这个委托实施;凭证参数被忽略

                }

               

            } else {

                NSLog(@"不是服务器信任的证书-没有挑战的必要了");

                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;//整个请求将被取消,凭证参数被忽略

            }

        }

        else {

            // client authentication-客户端身份验证

            SecIdentityRef identity = NULL;//p12数据中提取identity和trustobjects(可信任对象),并评估其可信度。

            SecTrustRef trust = NULL;//评估证书。这里的信任对象(trustobject),包括信任策略和其他用于判断证书是否可信的信息,都已经含在了PKCS数据中。要单独评估一个证书是否可信

            NSString *p12 = [[NSBundle mainBundle] pathForResource:@"client"ofType:@"p12"];

            NSFileManager *fileManager =[NSFileManager defaultManager];

           

            if(![fileManager fileExistsAtPath:p12])

            {

                NSLog(@"client.p12:notexist");

            }

            else

            {

                NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];

               

                if ([self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data])

                {

                    SecCertificateRefcertificate = NULL;

                    SecIdentityCopyCertificate(identity,&certificate);

                    const void*certs[] = {certificate};

                    CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);

                    credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge  NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];

                    disposition =NSURLSessionAuthChallengeUseCredential;

                }

            }

        }

        *_credential = credential;

        return disposition;

    }];

}

 

//读取p12文件中的密码

- (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {

    OSStatus securityError = errSecSuccess;

   

    //client certificate password

    //构造包含了密码的dictionary,用于传递给SecPKCS12Import函数。注意这里使用的是core foundation中的CFDictionaryRef,与NSDictionary完全等价

    NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"123456"

                                                                 forKey:(__bridge id)kSecImportExportPassphrase];

   

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

    securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);

   

    if(securityError == 0) {

       

        CFDictionaryRef myIdentityAndTrust =CFArrayGetValueAtIndex(items,0);

        const void*tempIdentity =NULL;

        tempIdentity= CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemIdentity);

        *outIdentity = (SecIdentityRef)tempIdentity;

        const void*tempTrust =NULL;

        tempTrust = CFDictionaryGetValue(myIdentityAndTrust,kSecImportItemTrust);

        *outTrust = (SecTrustRef)tempTrust;

       

    } else {

        NSLog(@"Failedwitherror code %d",(int)securityError);

        return NO;

    }

    return YES;

}

 

十:AFNewworking判断服务器证书是否有效

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust

                  forDomain:(NSString *)domain

{

/*

self.allowInvalidCertificates:是否信任服务器无效或过期的SSL证书。默认为“不”allowInvalidCertificates定义了客户端是否信任非法证书。一般来说,每个版本的iOS设备中,都会包含一些既有的CA根证书。如果接收到的证书是iOS信任的CA根证书签名的,那么则为合法证书;否则则为“非法”证书。

self.validatesDomainName:是否验证域名证书的CN字段。默认为“是”。validatesDomainName 是指是否校验在证书中的domain这一个字段。每个证书都会包含一个DomainName, 它可以是一个IP地址,一个域名或者一端带有通配符的域名。如*.google.com, www.google.com 都可以成为这个证书的DomainName。设置validatesDomainName=YES将严格地保证其安全性

self.SSLPinningMode: 验证证书的方式;

self.pinnedCertificates count:匹配的证书;pinnedCertificates 就是用来校验服务器返回证书的证书。通常都保存在mainBundle下。通常默认情况下,AFNetworking会自动寻找在mainBundle的根目录下所有的.cer文件并保存在pinnedCertificates数组里,以校验服务器返回的证书。

*/

    if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) {

        // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html

        //  According to the docs, youshould only trust your provided certs for evaluation.

        //  Pinned certificates are added tothe trust. Without pinned certificates,

        //  there is nothing to evaluateagainst.

        //

        //  From Apple Docs:

        //          "Do not implicitlytrust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors).

        //           Instead, add your own(self-signed) CA certificate to the list of trusted anchors."

        NSLog(@"Inorder to validate a domain name for self signed certificates, you MUST usepinning.");

        return NO;

    }

 

    NSMutableArray *policies = [NSMutableArray array];

    if (self.validatesDomainName) {//验证域名

        [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];

    } else {

        [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];

    }

 

    SecTrustSetPolicies(serverTrust,(__bridge CFArrayRef)policies);

 

    if (self.SSLPinningMode == AFSSLPinningModeNone) {//不验证证书内容

        return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust);

    } else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) {

        return NO;

    }

 

    switch (self.SSLPinningMode) {

        case AFSSLPinningModeNone:

        default:

            return NO;

        case AFSSLPinningModeCertificate: {//验证证书的全部内容;

            NSMutableArray *pinnedCertificates = [NSMutableArray array];

            for (NSData *certificateData in self.pinnedCertificates) {

                [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];

            }

            SecTrustSetAnchorCertificates(serverTrust,(__bridge CFArrayRef)pinnedCertificates);

 

            if (!AFServerTrustIsValid(serverTrust)) {

                return NO;

            }

 

            // obtain the chain after being validated, which *should* contain thepinned certificate in the last position (if it's the Root CA)

            NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust);

           

            for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) {

                if ([self.pinnedCertificates containsObject:trustChainCertificate]) {

                    return YES;

                }

            }

           

            return NO;

        }

        case AFSSLPinningModePublicKey: {//仅仅验证证书的公钥;

            NSUInteger trustedPublicKeyCount = 0;

            NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);

 

            for (id trustChainPublicKey in publicKeys) {

                for (id pinnedPublicKey in self.pinnedPublicKeys) {

                    if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) {

                       trustedPublicKeyCount += 1;

                    }

                }

            }

            return trustedPublicKeyCount > 0;

        }

    }

   

    return NO;

}

十一:在测试AFNetworking设置HTTPS描述。

1.  单向认证-只验证服务器证书的公钥-验证域名-信任无效证书。

测试结果:链接成功。

2.双向认证-验证服务器证书全部内容-验证域名-信任无效证书。

    测试结果:链接成功。

3. 单向认证-只验证服务器证书的公钥-验证域名-信任有效证书。

测试结果:链接失败。

4. 百度单向认证-只验证服务器证书全部内容-验证域名-信任有效证书。

测试结果:链接成功。

5. 百度单向认证-只验证服务器证书全部内容-验证域名-信任有效证书-导入证书未手动添加。

测试结果:链接成功。

6. 单向认证-只验证服务器证书公钥-验证域名-信任无效证书-导入证书手动添加。

测试结果:链接成功。

7. 单向认证-只验证服务器证书全部认证-验证域名-信任无效证书-导入证书手动添加。

测试结果:链接成功。

8. 单向认证-不验证服务器证书-验证域名-信任无效证书-导入证书-未手动添加。

测试结果:链接失败。

9. 单向认证-证书内容全部验证-验证域名-信任有效证书。

测试结果:链接失败。

10.单向认证-不验证证书内容-验证域名-信任有效证书。

测试结果:链接失败。

11.单向认证-证书内容全部验证-不验证域名-信任无效证书

测试结果:链接成功。

12.单向认证-证书内容全部验证-不验证域名-信任有效证书

测试结果:链接失败。

13.单向-不验证证书内容-没添加证书-不验证域名-信任无效证书

测试结果:链接成功。

14.单向认证-证书内容全部验证-未添加证书-验证域名-信任无效证书

测试结果:链接成功。

15.单向认证-不验证证书内容-未添加证书-不验证域名-信任无效证书

    测试结果:链接成功。

16.百度-单向认证-证书内容全部验证-验证域名-信任有效证书

测试结果:链接成功。

17.百度-单向认证-不验证证书-验证域名-信任有效证书

测试结果:链接成功。

18.百度-单向认证-不验证证书-验证域名-信任有效证书-移除证书

测试结果:链接成功。

19.百度-单向认证-不验证证书-验证域名-信任有效证书-使用错误证书

测试结果:链接成功。

20.百度-单向认证-不验证证书-不验证域名-信任有效证书-使用错误证书

测试结果:链接成功。

21.百度-单向-证书内容全部验证-不验证域名-信任有效证书-使用错误证书

测试结果:链接失败。

22.百度-单向-证书内容全部验证-验证域名-信任有效证书-使用错误证书

测试结果:链接失败。

23.百度-单向-证书内容全部验证-验证域名-信任有效证书-移除证书

测试结果:链接成功。

测试总结:

1.自签名证书默认是无效证书,是不可信任锚点。系统中CA根证书可信任锚点也就是有效证书。

2.自签名证书验证域名时必须同时验证证书,才能连接成功。

3.AFNetworking嵌入只需要将服务器证书导入项目中,pinnedCertificates 就是用来校验服务器返回证书的证书。通常都保存在mainBundle 下。通常默认情况下,AFNetworking会自动寻找在mainBundle的根目录下所有的.cer文件并保存在pinnedCertificates数组里,以校验服务器返回的证书。不需要手动添加也就是代码:[securityPolicy setPinnedCertificates:dataSet];

 
--------------------- 
原文:https://blog.csdn.net/dongruanlong/article/details/72641754 
 

你可能感兴趣的:(iOS)