精品国产一级在线观看,国产成人综合久久精品亚洲,免费一级欧美大片在线观看

打造安全的App!iOS安全系列之 HTTPS

責(zé)任編輯:editor005

作者:Jaminzzhang

2015-08-10 15:47:25

摘自:Jaminzzhang的博客

2 三個隨機數(shù):這三個隨機數(shù)構(gòu)成了后續(xù)通信過程中用來對數(shù)據(jù)進行對稱加密解密的“對話密鑰”。ps: 假如是自建證書的,則會跳過第二步,使用第三部進行驗證,因為自建證書的根CA的數(shù)字簽名未在操作系統(tǒng)的信任列表中。

1.jpg

如何打造一個安全的App?這是每一個移動開發(fā)者必須面對的問題。在移動App開發(fā)領(lǐng)域,開發(fā)工程師對于安全方面的考慮普遍比較欠缺,而由于iOS平臺的封閉性,遭遇到的安全問題相比于Android來說要少得多,這就導(dǎo)致了許多iOS開發(fā)人員對于安全性方面沒有太多的深入,但對于一個合格的軟件開發(fā)者來說,安全知識是必備知識之一。

對于未越獄的iOS設(shè)備來說,由于強大的沙箱和授權(quán)機制,以及Apple自己掌控的App Store, 基本上杜絕了惡意軟件的入侵。但除系統(tǒng)安全之外,我們還是面臨很多的安全問題:網(wǎng)絡(luò)安全、數(shù)據(jù)安全等,每一項涉及也非常廣,安全是非常大的課題,本人并非專業(yè)的安全專家,只是從開發(fā)者的角度,分析我們常遇到的各項安全問題,并提出通常的解決方法,與各位交流。

每一個軟件工程師都有義務(wù)保護用戶數(shù)據(jù)的隱私和安全。

首先是網(wǎng)絡(luò)安全,OSI模型各層都會面臨相應(yīng)的網(wǎng)絡(luò)安全問題,涉及寬廣,而網(wǎng)絡(luò)安全也是安全領(lǐng)域發(fā)展最為繁榮的領(lǐng)域。本文我們只是從移動應(yīng)用開發(fā)角度,以盡量簡單的方式,講解HTTPS核心概念知識,以及在iOS平臺上的實現(xiàn)。建議現(xiàn)在還在使用HTTP的應(yīng)用都升級到HTTPS。

引讀:互聯(lián)網(wǎng)全站HTTPS的時代已經(jīng)到來

1. HTTPS

其實HTTPS從最終的數(shù)據(jù)解析的角度,與HTTP沒有任何的區(qū)別,HTTPS就是將HTTP協(xié)議數(shù)據(jù)包放到SSL/TSL層加密后,在TCP/IP層組成IP數(shù)據(jù)報去傳輸,以此保證傳輸數(shù)據(jù)的安全;而對于接收端,在SSL/TSL將接收的數(shù)據(jù)包解密之后,將數(shù)據(jù)傳給HTTP協(xié)議層,就是普通的HTTP數(shù)據(jù)。HTTP和SSL/TSL都處于OSI模型的應(yīng)用層。從HTTP切換到HTTPS是一個非常簡單的過程,在做具體的切換操作之前,我們需要了解幾個概念:

SSL/TSL

關(guān)于SSL/TSL,阮一峰的兩篇博客文章做了很好的介紹:

SSL/TLS協(xié)議運行機制的概述

圖解SSL/TLS協(xié)議

簡單的來說,SSL/TSL通過四次握手,主要交換三個信息:

1. 數(shù)字證書:該證書包含了公鑰等信息,一般是由服務(wù)器發(fā)給客戶端,接收方通過驗證這個證書是不是由信賴的CA簽發(fā),或者與本地的證書相對比,來判斷證書是否可信;假如需要雙向驗證,則服務(wù)器和客戶端都需要發(fā)送數(shù)字證書給對方驗證;

2. 三個隨機數(shù):這三個隨機數(shù)構(gòu)成了后續(xù)通信過程中用來對數(shù)據(jù)進行對稱加密解密的“對話密鑰”。

首先客戶端先發(fā)第一個隨機數(shù)N1,然后服務(wù)器回了第二個隨機數(shù)N2(這個過程同時把之前提到的證書發(fā)給客戶端),這兩個隨機數(shù)都是明文的;而第三個隨機數(shù)N3(這個隨機數(shù)被稱為Premaster secret),客戶端用數(shù)字證書的公鑰進行非對稱加密,發(fā)給服務(wù)器;而服務(wù)器用只有自己知道的私鑰來解密,獲取第三個隨機數(shù)。只有,服務(wù)端和客戶端都有了三個隨機數(shù)N1+N2+N3,然后兩端就使用這三個隨機數(shù)來生成“對話密鑰”,在此之后的通信都是使用這個“對話密鑰”來進行對稱加密解密。因為這個過程中,服務(wù)端的私鑰只用來解密第三個隨機數(shù),從來沒有在網(wǎng)絡(luò)中傳輸過,這樣的話,只要私鑰沒有被泄露,那么數(shù)據(jù)就是安全的。

3. 加密通信協(xié)議:就是雙方商量使用哪一種加密方式,假如兩者支持的加密方式不匹配,則無法進行通信;

有個常見的問題,關(guān)于隨機數(shù)為什么要三個?只最后一個隨機數(shù)N3不可以么?

這是由于SSL/TLS設(shè)計,就假設(shè)服務(wù)器不相信所有的客戶端都能夠提供完全隨機數(shù),假如某個客戶端提供的隨機數(shù)不隨機的話,就大大增加了“對話密鑰”被破解的風(fēng)險,所以由三組隨機數(shù)組成最后的隨機數(shù),保證了隨機數(shù)的隨機性,以此來保證每次生成的“對話密鑰”安全性。

數(shù)字證書

數(shù)字證書是一個電子文檔,其中包含了持有者的信息、公鑰以及證明該證書有效的數(shù)字簽名。而數(shù)字證書以及相關(guān)的公鑰管理和驗證等技術(shù)組成了PKI(公鑰基礎(chǔ)設(shè)施)規(guī)范體系。一般來說,數(shù)字證書是由數(shù)字證書認(rèn)證機構(gòu)(Certificate authority,即CA)來負(fù)責(zé)簽發(fā)和管理,并承擔(dān)PKI體系中公鑰合法性的檢驗責(zé)任;數(shù)字證書的類型有很多,而HTTPS使用的是SSL證書。

怎么來驗證數(shù)字證書是由CA簽發(fā)的,而不是第三方偽造的呢? 在回答這個問題前,我們需要先了解CA的組織結(jié)構(gòu)。首先,CA組織結(jié)構(gòu)中,最頂層的就是根CA,根CA下可以授權(quán)給多個二級CA,而二級CA又可以授權(quán)多個三級CA,所以CA的組織結(jié)構(gòu)是一個樹結(jié)構(gòu)。對于SSL證書市場來說,主要被Symantec(旗下有VeriSign和GeoTrust)、Comodo SSL、Go Daddy 和 GlobalSign 瓜分。 了解了CA的組織結(jié)構(gòu)后,來看看數(shù)字證書的簽發(fā)流程:

blob.png

數(shù)字證書的簽發(fā)機構(gòu)CA,在接收到申請者的資料后進行核對并確定信息的真實有效,然后就會制作一份符合X.509標(biāo)準(zhǔn)的文件。證書中的證書內(nèi)容包括了持有者信息和公鑰等都是由申請者提供的,而數(shù)字簽名則是CA機構(gòu)對證書內(nèi)容進行hash加密后等到的,而這個數(shù)字簽名就是我們驗證證書是否是有可信CA簽發(fā)的數(shù)據(jù)。

blob.png

接收端接到一份數(shù)字證書Cer1后,對證書的內(nèi)容做Hash等到H1;然后在簽發(fā)該證書的機構(gòu)CA1的數(shù)字證書中找到公鑰,對證書上數(shù)字簽名進行解密,得到證書Cer1簽名的Hash摘要H2;對比H1和H2,假如相等,則表示證書沒有被篡改。但這個時候還是不知道CA是否是合法的,我們看到上圖中有CA機構(gòu)的數(shù)字證書,這個證書是公開的,所有人都可以獲取到。而這個證書中的數(shù)字簽名是上一級生成的,所以可以這樣一直遞歸驗證下去,直到根CA。根CA是自驗證的,即他的數(shù)字簽名是由自己的私鑰來生成的。合法的根CA會被瀏覽器和操作系統(tǒng)加入到權(quán)威信任CA列表中,這樣就完成了最終的驗證。所以,一定要保護好自己環(huán)境(瀏覽器/操作系統(tǒng))中根CA信任列表,信任了根CA就表示信任所有根CA下所有子級CA所簽發(fā)的證書,不要隨便添加根CA證書。

了解了上面兩個概念之后,對HTTPS就有了個初步的了解,下面我們看如何在iOS上實現(xiàn)對HTTPS的支持。

2. 實現(xiàn)支持HTTPS

首先,需要明確你使用HTTP/HTTPS的用途,因為OSX和iOS平臺提供了多種API,來支持不同的用途,官方文檔《Making HTTP and HTTPS Requests》有詳細(xì)的說明,而文檔《HTTPS Server Trust Evaluation》則詳細(xì)講解了HTTPS驗證相關(guān)知識,這里就不多說了。本文主要講解我們最常用的NSURLConnection支持HTTPS的實現(xiàn)(NSURLSession的實現(xiàn)方法類似,只是要求授權(quán)證明的回調(diào)不一樣而已),以及怎么樣使用AFNetworking這個非常流行的第三方庫來支持HTTPS。本文假設(shè)你對HTTP以及NSURLConnection的接口有了足夠的了解。

驗證證書的API

相關(guān)的Api在Security Framework中,驗證流程如下:

1). 第一步,先獲取需要驗證的信任對象(Trust Object)。這個Trust Object在不同的應(yīng)用場景下獲取的方式都不一樣,對于NSURLConnection來說,是從delegate方法-connection:willSendRequestForAuthenticationChallenge:回調(diào)回來的參數(shù)challenge中獲取([challenge.protectionSpace serverTrust])。

2). 使用系統(tǒng)默認(rèn)驗證方式驗證Trust Object。SecTrustEvaluate會根據(jù)Trust Object的驗證策略,一級一級往上,驗證證書鏈上每一級數(shù)字簽名的有效性(上一部分有講解),從而評估證書的有效性。

3). 如第二步驗證通過了,一般的安全要求下,就可以直接驗證通過,進入到下一步:使用Trust Object生成一份憑證([NSURLCredential credentialForTrust:serverTrust]),傳入challenge的sender中([challenge.sender useCredential:cred forAuthenticationChallenge:challenge])處理,建立連接。

4). 假如有更強的安全要求,可以繼續(xù)對Trust Object進行更嚴(yán)格的驗證。常用的方式是在本地導(dǎo)入證書,驗證Trust Object與導(dǎo)入的證書是否匹配。更多的方法可以查看Enforcing Stricter Server Trust Evaluation,這一部分在講解AFNetworking源碼中會講解到。

5). 假如驗證失敗,取消此次Challenge-Response Authentication驗證流程,拒絕連接請求。

ps: 假如是自建證書的,則會跳過第二步,使用第三部進行驗證,因為自建證書的根CA的數(shù)字簽名未在操作系統(tǒng)的信任列表中。

iOS授權(quán)驗證的API和流程大概了解了,下面,我們看看在NSURLConnection中的代碼實現(xiàn):

使用NSURLConnection支持HTTPS的實現(xiàn)

// Now start the connection NSURL * httpsURL = [NSURL URLWithString:@"https://www.google.com"]; self.connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:httpsURL] delegate:self]; //回調(diào) - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {   //1)獲取trust object   SecTrustRef trust = challenge.protectionSpace.serverTrust;   SecTrustResultType result;   //2)SecTrustEvaluate對trust進行驗證   OSStatus status = SecTrustEvaluate(trust, &result);   if (status == errSecSuccess &&     (result == kSecTrustResultProceed ||     result == kSecTrustResultUnspecified)) {     //3)驗證成功,生成NSURLCredential憑證cred,告知challenge的sender使用這個憑證來繼續(xù)連接     NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];     [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];   } else {     //5)驗證失敗,取消這次驗證流程     [challenge.sender cancelAuthenticationChallenge:challenge];

上面是代碼是通過系統(tǒng)默認(rèn)驗證流程來驗證證書的。假如我們是自建證書的呢?這樣Trust Object里面服務(wù)器的證書因為不是可信任的CA簽發(fā)的,所以直接使用SecTrustEvaluate進行驗證是不會成功。又或者,即使服務(wù)器返回的證書是信任CA簽發(fā)的,又如何確定這證書就是我們想要的特定證書?這就需要先在本地導(dǎo)入證書,設(shè)置成需要驗證的Anchor Certificate(就是根證書),再調(diào)用SecTrustEvaluate來驗證。代碼如下

//先導(dǎo)入證書 NSString * cerPath = ...; //證書的路徑 NSData * cerData = [NSData dataWithContentsOfFile:cerPath]; SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData)); self.trustedCertificates = @[CFBridgingRelease(certificate)]; //回調(diào) - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {   //1)獲取trust object   SecTrustRef trust = challenge.protectionSpace.serverTrust;   SecTrustResultType result;   //注意:這里將之前導(dǎo)入的證書設(shè)置成下面驗證的Trust Object的anchor certificate   SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)self.trustedCertificates);   //2)SecTrustEvaluate會查找前面SecTrustSetAnchorCertificates設(shè)置的證書或者系統(tǒng)默認(rèn)提供的證書,對trust進行驗證   OSStatus status = SecTrustEvaluate(trust, &result);   if (status == errSecSuccess &&     (result == kSecTrustResultProceed ||     result == kSecTrustResultUnspecified)) {     //3)驗證成功,生成NSURLCredential憑證cred,告知challenge的sender使用這個憑證來繼續(xù)連接     NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];     [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];   } else {     //5)驗證失敗,取消這次驗證流程     [challenge.sender cancelAuthenticationChallenge:challenge];

建議采用本地導(dǎo)入證書的方式驗證證書,來保證足夠的安全性。更多的驗證方法,請查看官方文檔《HTTPS Server Trust Evaluation》

使用AFNetworking來支持HTTPS

AFNetworking是iOS/OSX開發(fā)最流行的第三方開源庫之一,其作者是非常著名的iOS/OSX開發(fā)者Mattt Thompson,其博客NSHipster也是iOS/OSX開發(fā)者學(xué)習(xí)和開闊技術(shù)視野的好地方。AFNetworking已經(jīng)將上面的邏輯代碼封裝好,甚至更完善,在AFSecurityPolicy文件中,有興趣可以閱讀這個模塊的代碼;

AFNetworking上配置對HTTPS的支持非常簡單:

NSURL * url = [NSURL URLWithString:@"https://www.google.com"]; AFHTTPRequestOperationManager * requestOperationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url]; dispatch_queue_t requestQueue = dispatch_create_serial_queue_for_name("kRequestCompletionQueue"); requestOperationManager.completionQueue = requestQueue; AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; //allowInvalidCertificates 是否允許無效證書(也就是自建的證書),默認(rèn)為NO //如果是需要驗證自建證書,需要設(shè)置為YES securityPolicy.allowInvalidCertificates = YES; //validatesDomainName 是否需要驗證域名,默認(rèn)為YES; //假如證書的域名與你請求的域名不一致,需把該項設(shè)置為NO //主要用于這種情況:客戶端請求的是子域名,而證書上的是另外一個域名。因為SSL證書上的域名是獨立的,假如證書上注冊的域名是www.google.com,那么mail.google.com是無法驗證通過的;當(dāng)然,有錢可以注冊通配符的域名*.google.com,但這個還是比較貴的。 securityPolicy.validatesDomainName = NO; //validatesCertificateChain 是否驗證整個證書鏈,默認(rèn)為YES //設(shè)置為YES,會將服務(wù)器返回的Trust Object上的證書鏈與本地導(dǎo)入的證書進行對比,這就意味著,假如你的證書鏈?zhǔn)沁@樣的: //GeoTrust Global CA // Google Internet Authority G2 // *.google.com //那么,除了導(dǎo)入*.google.com之外,還需要導(dǎo)入證書鏈上所有的CA證書(GeoTrust Global CA, Google Internet Authority G2); //如是自建證書的時候,可以設(shè)置為YES,增強安全性;假如是信任的CA所簽發(fā)的證書,則建議關(guān)閉該驗證; securityPolicy.validatesCertificateChain = NO; requestOperationManager.securityPolicy = securityPolicy;

這就是AFNetworking的支持HTTPS的主要配置說明,AFHTTPSessionManager與之基本一致,就不重復(fù)了。

3. 總結(jié)

雖然HTTPS相比于HTTP來說,會有一定的性能上的劣勢,但對于網(wǎng)絡(luò)飛速發(fā)展,移動設(shè)備的性能成倍增長的今天,安全才是我們更應(yīng)該去考慮的。全網(wǎng)HTTPS并不是那么遙遠(yuǎn)。

鏈接已復(fù)制,快去分享吧

企業(yè)網(wǎng)版權(quán)所有?2010-2024 京ICP備09108050號-6京公網(wǎng)安備 11010502049343號

  • <menuitem id="jw4sk"></menuitem>

    1. <form id="jw4sk"><tbody id="jw4sk"><dfn id="jw4sk"></dfn></tbody></form>
      主站蜘蛛池模板: 府谷县| 屏东市| 静乐县| 额济纳旗| 凤山县| 诸暨市| 洛阳市| 德格县| 噶尔县| 九龙城区| 永寿县| 商丘市| 绥中县| 宣威市| 鞍山市| 蒲江县| 南投县| 汝南县| 南开区| 宝应县| 安仁县| 桃园市| 香河县| 武邑县| 准格尔旗| 永德县| 曲松县| 达尔| 阿图什市| 库伦旗| 密云县| 芜湖市| 西贡区| 资兴市| 全南县| 康乐县| 晋中市| 灵丘县| 沛县| 高邮市| 分宜县|