iOS開發(fā)API解讀之SSL/TLS連接

(原創(chuàng)內(nèi)容,轉(zhuǎn)載請(qǐng)注明出處)

本文將通過創(chuàng)建SSL/TLS連接到認(rèn)證的順序來(lái)一一講解SSL API的作用和實(shí)現(xiàn)捆昏。 (TLS是基于SSL的升級(jí)江掩,提升了SSL算法,也可以理解為TLS1.0 = SSL 3.0,下文中通用SSL來(lái)稱呼SSL/TLS)缎除。SSL原理網(wǎng)上一大堆,自行Google总寻。

創(chuàng)建SSL上下文

有SSL連接就需要SSLContext會(huì)話上下文來(lái)做基石器罐。一個(gè)上下文不能重復(fù)用于多個(gè)會(huì)話。

創(chuàng)建

SSLCreateContext(CFAllocatorRef __nullable alloc, SSLProtocolSide protocolSide, SSLConnectionType connectionType)

我們來(lái)看這個(gè)函數(shù)每個(gè)參數(shù)的具體意義:

CFAllocatorRef用于標(biāo)識(shí)初始化方式渐行。

SSLProtocolSide用來(lái)標(biāo)識(shí)這個(gè)SSL協(xié)議用于服務(wù)端還是客戶端轰坊。

SSLConnectionType用來(lái)標(biāo)識(shí)該上下文是基于流還是基于數(shù)據(jù)的通信,kSSLStreamType用于TCP通信祟印,kSSLDatagramType用于UDP通信肴沫。

創(chuàng)建好SSLContext之后,需要設(shè)置它的IO數(shù)據(jù)輸入輸出函數(shù)蕴忆,此函數(shù)也屬于配置SSL Session:

SSLSetIOFuncs (SSLContextRef context, SSLReadFunc readFunc, SSLWriteFunc writeFunc)

一個(gè)輸入輸出的回調(diào)函數(shù)應(yīng)該是這個(gè)樣子:

(*SSLReadFunc)(SSLConnectionRef connection, void *data, size_t *dataLength);

其中connection一般用來(lái)傳遞當(dāng)前使用SSLContext的對(duì)象颤芬,此函數(shù)收到數(shù)據(jù)的時(shí)候,便能通過connection橋接的self來(lái)把數(shù)據(jù)發(fā)送給self。

關(guān)聯(lián)

怎么設(shè)置connection站蝠?這樣:

SSLSetConnection(sslContext, (__bridge SSLConnectionRef)self);

設(shè)置SSL相關(guān)參數(shù)

配置SSL Session

初始化和關(guān)聯(lián)處理數(shù)據(jù)的對(duì)象關(guān)聯(lián)起來(lái)之后汰具,就該為SSL設(shè)置一些常用參數(shù)了!下面這個(gè)方法就是給SSL填充參數(shù)選項(xiàng)了:

SSLSetSessionOption(SSLContextRef context, SSLSessionOption option, Boolean value)

我們來(lái)看看SSLSessionOption都有些什么內(nèi)容菱魔!這些選項(xiàng)決定了SSLHandShake什么時(shí)候會(huì)返回一個(gè)狀態(tài)值留荔。所以,這些參數(shù)是很重要的澜倦!

typedef CF_ENUM(int, SSLSessionOption) {

// 服務(wù)器端認(rèn)證客戶端完成(OSStatus = errSSLServerAuthCompleted)聚蝶,客戶端此時(shí)可以通過手動(dòng)驗(yàn)證服務(wù)端證書來(lái)決定是否繼續(xù)SSL連接

//如果需要手動(dòng)驗(yàn)證服務(wù)器證書,就把這個(gè)選項(xiàng)設(shè)置為YES

kSSLSessionOptionBreakOnServerAuth = 0,

// 服務(wù)端要求客戶端提供證書(OSStatus = errSSLClientCertRequested)

kSSLSessionOptionBreakOnCertRequested = 1,

//客戶端已經(jīng)提供證書藻治,是否允許服務(wù)端對(duì)其進(jìn)行驗(yàn)證

kSSLSessionOptionBreakOnClientAuth = 2,

//如果開啟此選項(xiàng)碘勉,在協(xié)商好充足的密碼套件(cipher-suite)的前提下,才會(huì)開始一個(gè)非正確的SSL連接

kSSLSessionOptionFalseStart = 3,

//是否啟動(dòng)應(yīng)對(duì)BEAST攻擊的(1/n-1)記錄拆分栋艳,開啟后恰聘,TLS1.0會(huì)對(duì)cipher執(zhí)行記錄拆分

kSSLSessionOptionSendOneByteRecord = 4,

//在SSL連接進(jìn)行重新協(xié)商的時(shí)候,是否允許服務(wù)器標(biāo)識(shí)發(fā)生改變吸占。為了避免三重握手攻擊晴叨,默認(rèn)是禁止的

kSSLSessionOptionAllowServerIdentityChange = 5,

//開啟此選項(xiàng)后,SSL連接將使用低版本協(xié)議進(jìn)行連接失敗后的重試

kSSLSessionOptionFallback = 6,

//握手第一步(clientHello)消息時(shí)進(jìn)行打斷以便檢查SNI(Service Node Interface:不同域名使用不同證書)矾屯,該選項(xiàng)一般用在服務(wù)端

kSSLSessionOptionBreakOnClientHello = 7,

//是否重新協(xié)商密碼套件兼蕊,默認(rèn)是不允許的

kSSLSessionOptionAllowRenegotiation = 8,

};

以上選項(xiàng)會(huì)決定SSLHandShake什么時(shí)候會(huì)返回對(duì)應(yīng)握手步驟的狀態(tài)值,光是有這些件蚕,是不夠的孙技,我們還需要設(shè)置一些別的參數(shù)!Let‘s go排作!

SLSetClientSideAuthenticate(SSLContextRef context, SSLAuthenticate auth);

這個(gè)函數(shù)用在服務(wù)端(非必須)牵啦,用于設(shè)定客戶端驗(yàn)證標(biāo)識(shí)。默認(rèn)值是kNeverAuthenticate妄痪,既默認(rèn)不需要客戶端提供證書哈雏。

SSLSetProtocolVersionMin(SSLContextRef context, SSLProtocol minVersion)

SSLSetProtocolVersionMin函數(shù)用來(lái)設(shè)定支持的SSL協(xié)議最小版本

SSLSetProtocolVersionMax(SSLContextRef context, SSLProtocol maxVersion)

這個(gè)函數(shù)用來(lái)設(shè)定支持的SSL協(xié)議最大版本。 設(shè)置最大或者最小的協(xié)議版本號(hào)衫生,合法的版本號(hào)有這么幾個(gè):kSSLProtocol3(SSL v3.0)裳瘪、kTLSProtocol1(TLS v1.0)、kTLSProtocol11(TLS v1.1)罪针、kTLSProtocol12(TLS v1.2)以及kDTLSProtocol1(DTLS v1.0)

SSLSetPeerID(SSLContextRef context, const void *peerID, size_t peerIDLen);

SSLSetPeerID設(shè)置一個(gè)c字符串的data來(lái)作為當(dāng)前會(huì)話的唯一標(biāo)識(shí)符彭羹,比如IP地址+端口,在SSLHandShake握手之前是可選設(shè)置的泪酱。但是要想成功恢復(fù)某個(gè)會(huì)話時(shí)派殷,這個(gè)設(shè)置則是必須的还最,嘗試恢復(fù)SSL會(huì)話的時(shí)候會(huì)檢查上一個(gè)會(huì)話是否使用的是相同的peerID。

SSLSetPeerDomainName(SSLContextRef context, const char *peerName, size_t peerNameLen);

SSLSetPeerDomainName這個(gè)函數(shù)用來(lái)驗(yàn)證另一端的證書通用名稱字段毡惜,比如可以設(shè)置成“store.apple.com”憋活,如果證書中的通用名稱與設(shè)置的PeerDomainName不匹配時(shí),則會(huì)握手失敗虱黄,返回errSSLXCertChainInvalid狀態(tài)值。此功能是可選的吮成,并且只能在會(huì)話沒有開始時(shí)設(shè)置橱乱。(蘋果官方很推薦設(shè)置這個(gè)參數(shù)~)

SSLSetEnabledCiphers(SSLContextRef context,const SSLCipherSuite *ciphers, size_t numCiphers)

SetEnabledCiphers用來(lái)指定SSL會(huì)話使用的密碼套件,會(huì)話活躍的時(shí)候是不能設(shè)置的粱甫!如果要查詢會(huì)話正在使用的密碼套件泳叠,可以調(diào)用函數(shù)SSLGetEnabledCiphers來(lái)查詢到。

SSLSetCertificate(SSLContextRef context, CFArrayRef certRefs);

SSLSetCertificate這個(gè)函數(shù)很重要2柘NH摇!設(shè)置客戶端證書是可選的乌庶,如果服務(wù)端要求客戶端提供證書种蝶,則必須調(diào)用此函數(shù)設(shè)置好證書,設(shè)置證書的函數(shù)必須在SSLHandShake握手開始前或者返回errSSLClientCertRequested后調(diào)用瞒大。這個(gè)證書會(huì)在當(dāng)前會(huì)話有效螃征!certRefs數(shù)組必須在[0]位中放置一個(gè)SecIdentityRef對(duì)象,該對(duì)象標(biāo)識(shí)葉證書及其相應(yīng)的私鑰透敌。

還有很多很多的配置函數(shù)盯滚,不便一一列出。具體可以查看和官方文檔酗电。

接下來(lái)就是重頭戲了魄藕!

握手

都配置好了,就需要執(zhí)行SSL握手了撵术!執(zhí)行握手的方法如下:

OSStatus SSLHandshake(SSLContextRef context)

結(jié)果將會(huì)返回給OSStatus背率!一些比較常見的狀態(tài)值有這些:

errSSLUnknownRootCert(對(duì)方證書鏈的根證書未知)

errSSLCertExpired(證書過期)

errSSLXCertChainInvalid(另一端的證書鏈無(wú)效或者沒有證書)

errSSLClientCertRequested:(服務(wù)器需要客戶端提供證書,客戶端可以選擇檢查服務(wù)器的證書和可分辨名稱列表荷荤,然后根據(jù)驗(yàn)證結(jié)果來(lái)決定是否繼續(xù)握手退渗。如果之前沒有設(shè)置本地證書,則調(diào)用SSLSetCertificate設(shè)置證書蕴纳,然后再次調(diào)用SSLHandshake來(lái)恢復(fù)握手)

errSSLWouldBlock的返回值表示SSLHandshake必須再次調(diào)用(并且一次又一次地会油,直到返回其他的東西)

握手過程中,如果要手動(dòng)驗(yàn)證另一端證書古毛,在對(duì)方已經(jīng)發(fā)送證書的前提下可以通過SSLCopyPeerTrustSSLCopyPeerCertificates來(lái)得到對(duì)方的證書了翻翩! 驗(yàn)證完對(duì)方證書并且通過后都许,再次調(diào)用SSLHandShake()來(lái)繼續(xù)剛才的握手。 當(dāng)SSLHandShake返回noErr時(shí)嫂冻,就是握手成功完成啦胶征!

讀寫

握手成功以后,就可以通過

SSLWrite(SSLContextRef context, const void * _nullable data, sizet dataLength, size_t*processed)

來(lái)進(jìn)行數(shù)據(jù)寫入了桨仿。 數(shù)據(jù)讀取則是這個(gè)方法:

SSLRead(SSLContextRef context, const void * _nullable data, sizet dataLength, size_t *processed)

還有獲取緩存的數(shù)據(jù)等方法睛低,已經(jīng)不屬于建立SSL連接的范疇,此處不再贅述服傍。 比如:

SSLGetBufferedReadSize

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钱雷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吹零,更是在濱河造成了極大的恐慌罩抗,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灿椅,死亡現(xiàn)場(chǎng)離奇詭異套蒂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)茫蛹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門操刀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人麻惶,你說我怎么就攤上這事馍刮。” “怎么了窃蹋?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵卡啰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我警没,道長(zhǎng)匈辱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任杀迹,我火速辦了婚禮亡脸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘树酪。我一直安慰自己浅碾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布续语。 她就那樣靜靜地躺著垂谢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疮茄。 梳的紋絲不亂的頭發(fā)上滥朱,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天根暑,我揣著相機(jī)與錄音,去河邊找鬼徙邻。 笑死排嫌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的缰犁。 我是一名探鬼主播淳地,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼帅容!你這毒婦竟也來(lái)了薇芝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤丰嘉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后嚷缭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饮亏,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年阅爽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了路幸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡付翁,死狀恐怖简肴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情百侧,我是刑警寧澤砰识,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站佣渴,受9級(jí)特大地震影響辫狼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辛润,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一膨处、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧砂竖,春花似錦真椿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至三圆,卻和暖如春狞换,著一層夾襖步出監(jiān)牢的瞬間避咆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工修噪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留查库,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓黄琼,卻偏偏與公主長(zhǎng)得像樊销,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子脏款,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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

  • 互聯(lián)網(wǎng)的通信安全围苫,建立在SSL/TLS協(xié)議之上。 本文簡(jiǎn)要介紹SSL/TLS協(xié)議的運(yùn)行機(jī)制撤师。文章的重點(diǎn)是設(shè)計(jì)思想和...
    拉肚閱讀 2,643評(píng)論 0 6
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測(cè)試 ...
    KeKeMars閱讀 6,336評(píng)論 0 6
  • 前言 HTTPS是什么相信大家都知道剂府,如果你不知道。剃盾。腺占。請(qǐng)關(guān)閉此文!Q髑础衰伯!HTTP的數(shù)據(jù)是明文傳輸?shù)模瑳]有安全性可言...
    MxlZlh閱讀 6,459評(píng)論 0 9
  • 本文是對(duì)HTTP—TCP/IP—SOCKET理解及淺析的補(bǔ)充积蔚,如有需要意鲸,請(qǐng)查看上篇文章。 SSL與TLS SSL協(xié)...
    蘇州丸子閱讀 5,836評(píng)論 0 7
  • 今天是我日精進(jìn)的第115天和大家分享我今天的進(jìn)步尽爆,我們互相勉勵(lì)怎顾,攜手前行。每天進(jìn)步一點(diǎn)點(diǎn)漱贱,距離成功便不遠(yuǎn)杆勇。 1、比...
    環(huán)宇廣告1姜波閱讀 84評(píng)論 0 0