https筆記

HTTPS就是將HTTP協(xié)議數(shù)據(jù)包放到SSL/TSL層加密后,在TCP/IP層組成IP數(shù)據(jù)報(bào)去傳輸咆课,以此保證傳輸數(shù)據(jù)的安全末誓。
證書分為兩種扯俱,一種是花錢向CA(證書認(rèn)證的機(jī)構(gòu))購買的證書,服務(wù)端如果使用的是這類證書的話喇澡,那一般客戶端不需要做什么迅栅,用HTTPS進(jìn)行請(qǐng)求就行了,蘋果內(nèi)置了那些受信任的根證書的晴玖。另一種是自己制作的證書读存,使用這類證書的話是不受信任的(當(dāng)然也不用花錢買),因此需要我們?cè)诖a中將該證書設(shè)置為信任證書呕屎。
對(duì)于一般的小型網(wǎng)站尤其是博客让簿,可以使用自簽名證書來構(gòu)建安全網(wǎng)絡(luò),所謂自簽名證書秀睛,就是自己扮演 CA 機(jī)構(gòu)尔当,自己給自己的服務(wù)器頒發(fā)證書。

SSL協(xié)議的握手過程:(參考

bg2014092004.png

SSL/TSl握手階段的詳細(xì)過程

  • 首先蹂安,客戶端(通常是瀏覽器)先向服務(wù)器發(fā)出加密通信的請(qǐng)求椭迎,這被叫做ClientHello請(qǐng)求。
    在這一步藤抡,客戶端主要向服務(wù)器提供以下信息侠碧。
    (1) 支持的協(xié)議版本,比如TLS 1.0版缠黍。
    (2) 一個(gè)客戶端生成的隨機(jī)數(shù)弄兜,稍后用于生成"對(duì)話密鑰"。
    (3) 支持的加密方法瓷式,比如RSA公鑰加密替饿。
    (4) 支持的壓縮方法。
  • 服務(wù)器收到客戶端請(qǐng)求后贸典,向客戶端發(fā)出回應(yīng)视卢,這叫做SeverHello。服務(wù)器的回應(yīng)包含以下內(nèi)容廊驼。
    (1) 確認(rèn)使用的加密通信協(xié)議版本据过,比如TLS 1.0版本。如果瀏覽器與服務(wù)器支持的版本不一致妒挎,服務(wù)器關(guān)閉加密通信绳锅。
    (2) 一個(gè)服務(wù)器生成的隨機(jī)數(shù),稍后用于生成"對(duì)話密鑰"酝掩。
    (3) 確認(rèn)使用的加密方法鳞芙,比如RSA公鑰加密。
    (4) 服務(wù)器證書。
  • 客戶端收到服務(wù)器回應(yīng)以后原朝,首先驗(yàn)證服務(wù)器證書驯嘱。如果證書不是可信機(jī)構(gòu)頒布、或者證書中的域名與實(shí)際域名不一致喳坠、或者證書已經(jīng)過期鞠评,就會(huì)向訪問者顯示一個(gè)警告,由其選擇是否還要繼續(xù)通信丙笋。
    如果證書沒有問題谢澈,客戶端就會(huì)從證書中取出服務(wù)器的公鑰。然后御板,向服務(wù)器發(fā)送下面三項(xiàng)信息:
    (1) 一個(gè)隨機(jī)數(shù)锥忿。該隨機(jī)數(shù)用服務(wù)器公鑰加密,防止被竊聽怠肋。
    (2) 編碼改變通知敬鬓,表示隨后的信息都將用雙方商定的加密方法和密鑰發(fā)送。
    (3) 客戶端握手結(jié)束通知笙各,表示客戶端的握手階段已經(jīng)結(jié)束钉答。這一項(xiàng)同時(shí)也是前面發(fā)送的所有內(nèi)容的hash值,用來供服務(wù)器校驗(yàn)杈抢。
    上面第一項(xiàng)的隨機(jī)數(shù)数尿,是整個(gè)握手階段出現(xiàn)的第三個(gè)隨機(jī)數(shù),又稱"pre-master key"惶楼。有了它以后右蹦,客戶端和服務(wù)器就同時(shí)有了三個(gè)隨機(jī)數(shù),接著雙方就用事先商定的加密方法歼捐,各自生成本次會(huì)話所用的同一把"會(huì)話密鑰"何陆。
  • 服務(wù)器收到客戶端的第三個(gè)隨機(jī)數(shù)pre-master key之后,計(jì)算生成本次會(huì)話所用的"會(huì)話密鑰"豹储。然后贷盲,向客戶端最后發(fā)送下面信息。
    (1)編碼改變通知剥扣,表示隨后的信息都將用雙方商定的加密方法和密鑰發(fā)送巩剖。
    (2)服務(wù)器握手結(jié)束通知,表示服務(wù)器的握手階段已經(jīng)結(jié)束钠怯。這一項(xiàng)同時(shí)也是前面發(fā)送的所有內(nèi)容的hash值球及,用來供客戶端校驗(yàn)。
    至此呻疹,整個(gè)握手階段全部結(jié)束。接下來,客戶端與服務(wù)器進(jìn)入加密通信刽锤,就完全是使用普通的HTTP協(xié)議镊尺,只不過用"會(huì)話密鑰"加密內(nèi)容。

證書

證書的申請(qǐng)過程
  • 證書申請(qǐng)者向頒發(fā)證書的可信第三方CA提交申請(qǐng)證書相關(guān)信息并思,包括:申請(qǐng)者域名庐氮、申請(qǐng)者生成的公鑰(私鑰自己保存)及證書請(qǐng)求文件.cer等
  • CA通過線上、線下等多種手段驗(yàn)證證書申請(qǐng)者提供的信息合法和真實(shí)性宋彼。
  • 當(dāng)證書申請(qǐng)者提供的信息審核通過后弄砍,CA向證書申請(qǐng)者頒發(fā)證書,證書內(nèi)容包括明文信息和簽名信息输涕。其中明文信息包括證書頒發(fā)機(jī)構(gòu)音婶、證書有效期、域名莱坎、申請(qǐng)者相關(guān)信息及申請(qǐng)者公鑰等衣式,簽名信息是使用CA私鑰進(jìn)行加密的明文信息。當(dāng)證書申請(qǐng)者獲取到證書后檐什,可以通過安裝的CA證書中的公鑰對(duì)簽名信息進(jìn)行解密并與明文信息進(jìn)行對(duì)比來驗(yàn)證簽名的完整性碴卧。
證書的驗(yàn)證過程

TSL/SSL的握手過程里client會(huì)拿到server返回的證書并且驗(yàn)證證書本身的合法性(驗(yàn)證簽名完整性,驗(yàn)證證書有效期等)

  • 驗(yàn)證證書頒發(fā)者的合法性(查找頒發(fā)者的證書并檢查其合法性乃正,這個(gè)過程是遞歸的)
  • 證書驗(yàn)證的遞歸過程最終會(huì)成功終止住册,而成功終止的條件是:證書驗(yàn)證過程中遇到了錨點(diǎn)證書,錨點(diǎn)證書通常指:嵌入到操作系統(tǒng)中的根證書(權(quán)威證書頒發(fā)機(jī)構(gòu)頒發(fā)的自簽名證書)瓮具。
證書驗(yàn)證失敗的原因
  • 無法找到證書的頒發(fā)者
  • 證書過期
  • 驗(yàn)證過程中遇到了自簽名證書荧飞,但該證書不是錨點(diǎn)證書。
  • 無法找到錨點(diǎn)證書(即在證書鏈的頂端沒有找到合法的根證書)
  • 訪問的server的dns地址和證書中的地址不同
iOS實(shí)現(xiàn)支持HTTPS

在OC中當(dāng)使用NSURLConnectionNSURLSession建立URL并向服務(wù)器發(fā)送https請(qǐng)求獲取資源時(shí)搭综,服務(wù)器會(huì)使用HTTP狀態(tài)碼401進(jìn)行響應(yīng)(即訪問拒絕)垢箕。此時(shí)NSURLConnection或NSURLSession會(huì)接收到服務(wù)器需要授權(quán)的響應(yīng),當(dāng)客戶端授權(quán)通過后兑巾,才能繼續(xù)從服務(wù)器獲取數(shù)據(jù)条获。如下圖所示:

image.png

非自簽名證書驗(yàn)證實(shí)現(xiàn)

當(dāng)客戶端發(fā)送https請(qǐng)求后,服務(wù)器會(huì)返回需要授權(quán)的相關(guān)信息蒋歌,對(duì)于NSURLSession而言,帅掘,需要代理對(duì)象實(shí)現(xiàn)URLSession:task:didReceiveChallenge:completionHandler:方法。

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    NSURLCredential *credential = nil;
    
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    SecTrustResultType result;
    OSStatus status = SecTrustEvaluate(trust, &result);
    if (status == kSecTrustResultUnspecified || status == kSecTrustResultProceed) {
        credential = [NSURLCredential credentialForTrust:trust];
        if (credential) {
             disposition = NSURLSessionAuthChallengeUseCredential;
        }
    }
    completionHandler(disposition, credential);
}
  • NSURLSessionAuthChallengePerformDefaultHandling處理請(qǐng)求堂油,就好像代理沒有提供一個(gè)代理方法來處理認(rèn)證請(qǐng)求
  • NSURLSessionAuthChallengeRejectProtectionSpace拒接認(rèn)證請(qǐng)求修档。基于服務(wù)器響應(yīng)的認(rèn)證類型府框,URL加載類可能會(huì)多次調(diào)用代理方法吱窝。
SecTrustRef

表示需要驗(yàn)證的信任對(duì)象(Trust Object),在此指的是challenge.protectionSpace.serverTrust。包含待驗(yàn)證的證書和支持的驗(yàn)證方法等院峡。

SecTrustResultType

表示驗(yàn)證結(jié)果兴使。其中 kSecTrustResultProceed表示serverTrust驗(yàn)證成功,且該驗(yàn)證得到了用戶認(rèn)可(例如在彈出的是否信任的alert框中選擇always trust)照激。 kSecTrustResultUnspecified表示 serverTrust驗(yàn)證成功发魄,此證書也被暗中信任了,但是用戶并沒有顯示地決定信任該證書俩垃。 兩者取其一就可以認(rèn)為對(duì)serverTrust驗(yàn)證成功励幼。

SecTrustEvaluate

函數(shù)內(nèi)部遞歸地從葉節(jié)點(diǎn)證書到根證書驗(yàn)證。使用系統(tǒng)默認(rèn)的驗(yàn)證方式驗(yàn)證Trust Object口柳,根據(jù)上述證書鏈的驗(yàn)證可知苹粟,系統(tǒng)會(huì)根據(jù)Trust Object的驗(yàn)證策略,一級(jí)一級(jí)往上啄清,驗(yàn)證證書鏈上每一級(jí)證書有效性六水。

對(duì)于非自簽名的證書,即使服務(wù)器返回的證書是信任的CA頒發(fā)的辣卒,假如有更強(qiáng)的安全要求掷贾,可以繼續(xù)對(duì)Trust Object進(jìn)行更嚴(yán)格的驗(yàn)證。常用的方式是在本地導(dǎo)入證書荣茫,并將導(dǎo)入的證書設(shè)置成需要參與驗(yàn)證的錨點(diǎn)證書想帅,再調(diào)用SecTrustEvaluate通過本地導(dǎo)入的證書來驗(yàn)證服務(wù)器證書是否是可信的。如果服務(wù)器證書是這個(gè)錨點(diǎn)證書對(duì)應(yīng)CA或者子CA頒發(fā)的啡莉,或服務(wù)器證書本身就是這個(gè)錨點(diǎn)證書港准,則證書信任通過。如下代碼:

NSString *cerPath = ...;//證書在本次的路徑
NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)cerPath);
self.trustedCertificates = @[CFBridgingRelease(certificate)];

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    NSURLCredential *credential = nil;
    SecTrustRef trust = challenge.protectionSpace.serverTrust;
    SecTrustResultType result;
    
    //將之前導(dǎo)入的證書設(shè)置成下面驗(yàn)證的Trust Object的錨點(diǎn)證書
    SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)self.trustedCertificates);
    //通過本地導(dǎo)入的證書來驗(yàn)證服務(wù)器返回的證書是否可信
    OSStatus status = SecTrustEvaluate(trust, &result);
    if (status == kSecTrustResultUnspecified || status == kSecTrustResultProceed) {
        credential = [NSURLCredential credentialForTrust:trust];
        if (credential) {
            disposition = NSURLSessionAuthChallengeUseCredential;
        }
    }
    
    completionHandler(disposition, credential);
}

自簽名證書

對(duì)于自簽名證書咧欣,這樣Trust Object中的服務(wù)器證書是不可信任的CA頒發(fā)的浅缸,直接使用SecTrustEvaluate驗(yàn)證是不會(huì)成功的。
可以采取下述簡(jiǎn)單代碼繞過HTTPS的驗(yàn)證:

[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
 [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
綜上對(duì)非自建和自建證書驗(yàn)證過程的分析魄咕,可以總結(jié)如下:
  • 獲取需要驗(yàn)證的信任對(duì)象(Trust Object)衩椒。對(duì)于NSURLSession來說,
    是從delegate方法URLSession:task:didReceiveChallenge:completionHandler:回調(diào)回來的參數(shù)challenge中獲取(challenge.protectionSpace.serverTrust) 哮兰。
    使用系統(tǒng)默認(rèn)驗(yàn)證方式驗(yàn)證Trust Object毛萌。
  • SecTrustEvaluate會(huì)根據(jù)Trust Object的驗(yàn)證策略,一級(jí)一級(jí)往上喝滞,驗(yàn)證證書鏈上每一級(jí)數(shù)字簽名的有效性阁将,從而評(píng)估證書的有效性。
  • 如第二步驗(yàn)證通過了右遭,一般的安全要求下做盅,就可以直接驗(yàn)證通過缤削,進(jìn)入到下一步:使用Trust Object生成一份憑證([NSURLCredential credentialForTrust:serverTrust]),傳入block中 completionHandler(disposition, credential)處理吹榴,建立連接僻他。
  • 假如有更強(qiáng)的安全要求,可以繼續(xù)對(duì)Trust Object進(jìn)行更嚴(yán)格的驗(yàn)證腊尚。常用的方式是在本地導(dǎo)入證書,驗(yàn)證Trust Object與導(dǎo)入的證書是否匹配满哪。
  • 假如驗(yàn)證失敗婿斥,取消此次Challenge-Response Authentication驗(yàn)證流程,拒絕連接請(qǐng)求哨鸭。
  • 假如是自建證書的民宿,則不使用第二步系統(tǒng)默認(rèn)的驗(yàn)證方式,因?yàn)樽越ㄗC書的根CA的數(shù)字簽名未在操作系統(tǒng)的信任列表中像鸡。

在AFNetwoking的AFURLSessionManager.m這個(gè)文件里實(shí)現(xiàn)了代理方法URLSession:task:didReceiveChallenge:completionHandler:并且在代理方法里對(duì)服務(wù)器返回的證書做了驗(yàn)證活鹰。驗(yàn)證的方法是evaluateServerTrust:forDomain:(NSString *)domain
AFNetwoking提供了一個(gè)類AFSecurityPolicy,它有一個(gè)屬性:

typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
    AFSSLPinningModeNone,
    AFSSLPinningModePublicKey,
    AFSSLPinningModeCertificate,
};
@property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode;

這個(gè)枚舉值決定了按哪種方式來驗(yàn)證服務(wù)器返回的證書只估。默認(rèn)值是AFSSLPinningModeNone志群。

  • AFSSLPinningModeNone:這會(huì)通過SecTrustEvaluate來驗(yàn)證服務(wù)器返回的證書,對(duì)于CA認(rèn)證的證書可以選用這個(gè)值蛔钙;
  • AFSSLPinningModeCertificate:如果使用了CA認(rèn)證的證書锌云,并且在本地也導(dǎo)入了證書作為錨點(diǎn)證書來驗(yàn)證服務(wù)器返回的證書,可以用這個(gè)值吁脱。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末桑涎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兼贡,更是在濱河造成了極大的恐慌攻冷,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遍希,死亡現(xiàn)場(chǎng)離奇詭異等曼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)孵班,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門涉兽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來峭火,“玉大人敬辣,你說我怎么就攤上這事卤档∈崃荩” “怎么了别惦?”我有些...
    開封第一講書人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵潭枣,是天一觀的道長(zhǎng)绞蹦。 經(jīng)常有香客問我拳恋,道長(zhǎng),這世上最難降的妖魔是什么渴肉? 我笑而不...
    開封第一講書人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任冗懦,我火速辦了婚禮,結(jié)果婚禮上仇祭,老公的妹妹穿的比我還像新娘披蕉。我一直安慰自己,他們只是感情好乌奇,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開白布没讲。 她就那樣靜靜地躺著,像睡著了一般礁苗。 火紅的嫁衣襯著肌膚如雪爬凑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,166評(píng)論 1 308
  • 那天试伙,我揣著相機(jī)與錄音嘁信,去河邊找鬼。 笑死疏叨,一個(gè)胖子當(dāng)著我的面吹牛潘靖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播考廉,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼秘豹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了昌粤?” 一聲冷哼從身側(cè)響起既绕,我...
    開封第一講書人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涮坐,沒想到半個(gè)月后凄贩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡袱讹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年疲扎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捷雕。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡椒丧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出救巷,到底是詐尸還是另有隱情壶熏,我是刑警寧澤,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布浦译,位于F島的核電站棒假,受9級(jí)特大地震影響溯职,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帽哑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一谜酒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧妻枕,春花似錦僻族、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至康嘉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間籽前,已是汗流浹背亭珍。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枝哄,地道東北人肄梨。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像挠锥,于是被迫代替她去往敵國(guó)和親众羡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容