https证书验证

废话开篇:https 证书是什么?如何进行认证呢?带着这些疑问来简单的实现一下验证过程

简单的了解一下 https 在数据传输前的一些操作,如图:

这里总结一下上面的流程图关键的步骤:

1、认证网络请求的安全性

服务器会在建立真正的数据传输之前返回一个公钥数字证书。这里客户端需要在 URLSession 进行认证挑战方法回调里进行判断然后确定是否要继续进行请求。代理方法如下:

- (void)URLSession:(NSURLSession *)session

              task:(NSURLSessionTask *)task

didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge

 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
复制代码

可以这样理解,URLSessionhttps 网络请求的时候其实会把请求鉴权的权限通过代理的方法给暴露出来,是否信任并继续建立连接可以按照特定规则去执行(如自签证书),只有 https 请求会走代理方法,http 则不进行回调,这也是为什么 iOS系统 为什么提倡使用 https 的原因。

2、认证通过,通过公私钥非对称加密方式对最后的对称加密密钥进行加、解密:

这话听起来有点绕,基于第一步的公钥数字证书信任,那么,生成一个用于请求数据对称加密的密钥(对称加密更快),用这个公钥进行非对称加密,在由服务器的私钥进行解密,得到这个密钥,那么,真正建立的数据传输就以此密钥进行加、解密。

下面,模拟一下如何进行的公钥证书受信

创建 公钥.der证书.cer 文件

在终端依次输入如下命令:


//生成私钥
openssl genrsa -out private_key.pem 1024

//获取 证书.cer
openssl req -new -key private_key.pem -out rsaCertReq.csr

openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt

//将 .crt 格式证书转换为 .cer 格式证书,后面iOS程序里需要 .cer格式证书
openssl x509 -in rsaCert.crt -out rsaCert.cer -outform der

//获得 公钥.der
openssl x509 -outform der -in rsaCert.crt -out public_key.der

复制代码

过程中会有一些简单信息输入,这里没有特别的要求,文件创建后目录如图:

image.png

.cer 格式证书公钥.der 格式证书 全部拖到工程里:

image.png

下面输出一段代码,用 .cer 证书去验证 公钥.der 是否可信。


- (void)trustIsVaild

{
    //获取工程下所有cer证书(https 网络请求鉴权必需证书)
    NSArray *paths = [[NSBundle mainBundle] pathsForResourcesOfType:@"cer" inDirectory:@"."];

    //保存工程内的所有 cer 证书(并在后面设置为鉴权锚点)
    NSMutableArray *pinnedCertificates = [NSMutableArray array];

    for (NSString *path in paths) {

        NSData *certificateData = [NSData dataWithContentsOfFile:path];

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

    }

    //获取工程下的公钥数字证书(在https网络请求认证挑战中由服务器返回)
    NSString * publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"];

    NSData *derData = [[NSData alloc] initWithContentsOfFile:publicKeyPath];

    //证书资源
    SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)derData);

    //验证政策设置
    SecPolicyRef myPolicy = SecPolicyCreateBasicX509();

    SecTrustRef myTrust;

    //SecTrust 赋值
    OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);

    if (status == noErr) {
        //设置证书锚点(这里的意思就是如果鉴权到指定的证书是有效的,那么,就信任此公钥数字签名,这里如果不设置,那么就会一直找向根证书,由于工程里的公钥数字证书是自签的,所以,一定不会受信)
        SecTrustSetAnchorCertificates(myTrust, ( __bridge CFArrayRef)pinnedCertificates);

        SecTrustResultType result;

        if (SecTrustEvaluate(myTrust, &result) == 0) {

            //kSecTrustResultUnspecified 隐式信任 
            //kSecTrustResultProceed 可继续进行
            if ((result == kSecTrustResultUnspecified || result == kSecTrustResultProceed)) {

                NSLog(@"受信任的证书");

            } else {

                NSLog(@"未受信任的证书");

            }

        } else {

            NSLog(@"未受信任的证书初始化操作失败");

        }

    }

}
复制代码

运行如下:

image.png

顺便输出一下不设置 证书锚点 控制台内容:

if (status == noErr) {
        //不设置锚点
        //SecTrustSetAnchorCertificates(myTrust, (__bridge CFArrayRef)pinnedCertificates);

        SecTrustResultType result;

        if (SecTrustEvaluate(myTrust, &result) == 0) {

            if ((result == kSecTrustResultUnspecified || result == kSecTrustResultProceed)) {

                NSLog(@"受信任的证书");

            } else {

                NSLog(@"未受信任的证书");
            }
        } else {

            NSLog(@"未受信任的证书初始化操作失败");
        }
    }
复制代码
image.png

到这里,公钥证书如果受信,那么,下一步就规定一个 对称加密 session key 用这个公钥加密,发送到服务器,然后用对应的私钥解密,供以后的数据传输进行 对称加密 操作。

所以,移动端在做自定义证书鉴权的时候就需要存储服务器生成的 .cer 证书文件!

AFNetworking 下的鉴权方式处理相对复杂,因为 URLSession 的认证挑战回调是允许程序员全部无条件开启的,所以,AFNetworking 在默认鉴权行为的基础上添加了几种自定义鉴权方式:

typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {

    AFSSLPinningModeNone,//无条件开启

    AFSSLPinningModePublicKey,//认证公钥内容

    AFSSLPinningModeCertificate,//认证证书

};
复制代码

而且,在此之前 AFNetworking 通过

@property (readwrite, nonatomic, copy) AFURLSessionTaskAuthenticationChallengeBlock authenticationChallengeHandler;
复制代码

暴露给外界闭包进行自定义鉴权逻辑及处理结果。

- (void)URLSession:(NSURLSession *)session

              task:(NSURLSessionTask *)task

didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
     BOOL evaluateServerTrust = NO;
     NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
     NSURLCredential *credential = nil;

     //AFNetworking 暴露给程序员自定义处理入口
     if (self.authenticationChallengeHandler) {
          id result = self.authenticationChallengeHandler(....);
          ... (解析处理结果)
     }
    ...(证书认证处理代码)

    //最后调用 completionHandler 继续执行操作
    if (completionHandler) {

        completionHandler(disposition, credential);

    }
}
复制代码

disposition: 可以设置继续鉴权挑战(NSURLSessionAuthChallengeUseCredential) 或者中断鉴权挑战(NSURLSessionAuthChallengeCancelAuthenticationChallenge

credential: 如果证书认证通过则直接进行赋值,

credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
复制代码

否则为 nil

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,619评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,163评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 171,789评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,911评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,920评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,410评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,788评论 3 428
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,762评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,293评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,328评论 3 345
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,456评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,063评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,775评论 3 337
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,231评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,363评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,995评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,519评论 2 365

推荐阅读更多精彩内容