HTTPS的學習總結

HTTPS學習總結

簡述

HTTPS對比HTTP就多了一個安全層SSL/TLS,具體就是驗證服務端的證書和對內容進行加密。ios

先來看看HTTP和HTTPS的區別 
我用AFN訪問http下的httpbin.org/image/png 
而後用Charles抓一下包,能夠看到傳輸的圖片 
http的數據
而後訪問HTTPS下的https://httpbin.org/image/png 
再抓包,看到數據是亂碼,這就是加密事後的數據 
https的數據git

關於加密算法

1)對稱加密:密鑰只有一個,加密解密爲同一個密碼,且加解密速度快,典型的對稱加密算法有DES、AES等;github

2)非對稱加密:非對稱加密算法須要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,若是用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;若是用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。由於加密和解密使用的是兩個不一樣的密鑰,因此這種算法叫做非對稱加密算法。算法

過程就像咱們用github的時候也是這樣,咱們電腦這裏生成私鑰和公鑰,公鑰上傳到github,私鑰添加到咱們電腦的ssh裏,這樣github給咱們傳輸數據就是用咱們上傳的公鑰來加密,咱們得到數據後會用私鑰去解密。json

什麼是SSL/TLS

TLS是 Transport Layer Security的縮寫,傳輸層安全性協議,SSL是Secure Sockets Layer的縮寫,安全sokects層協議。SSL/TLS有不少好處,強大的驗證,算法靈活,容易部署和使用。缺點是增長處理器的負擔,可是消耗的性能很小,對比安全性來講能夠忽略不計。api

通訊過程

通訊過程有四次握手。 
一、客戶端發送請求,服務器返回公鑰給客戶端; 
二、客戶端生成對稱加密祕鑰,用公鑰對其進行加密後,返回給服務器; 
三、服務器收到後,利用私鑰解開獲得對稱加密祕鑰,保存; 
四、以後的交互都使用對稱加密後的數據進行交互。安全

HTTPS通訊的優勢 
1)客戶端產生的密鑰只有客戶端和服務器端能獲得;服務器

2)加密的數據只有客戶端和服務器端才能獲得明文;網絡

3)客戶端到服務端的通訊是安全的。app

如何得到證書

1.向CA申請證書

電子商務認證受權機構(CA, Certificate Authority),也稱爲電子商務認證中心,是負責發放和管理數字證書的權威機構。 
這裏就不細說了。

2.自制證書

還有一種方式就是自制證書,自制證書的證書是用OpenSSL生成的。OpenSSL 是一個強大的安全套接字層密碼庫,囊括主要的密碼算法、經常使用的密鑰和證書封裝管理功能及SSL協議,而且已經在github上開源。

OpenSSL的各類指令 
OpenSSL

自制證書的命令是

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX

剛開始輸入命令就會自動生成key.pem 
輸入命令後會讓你輸入密碼、國家、省市、組織(公司)、名字等信息 
輸入完成便會生成證書cert.pem

關於命令的一些選項:

  • req 是證書請求和生成的程序
  • -x509 一種證書標準
  • -newkey arg,arg是參數,例如rsa:2048是指生成2048位的rsa key
  • -keyout filename 輸出的根證書文件名
  • -out filename 輸出的標準證書文件嗎
  • -day n 用X.509標準的話要指定驗證多少天,默認30
  • *

預覽cert.pem能夠看到剛纔輸入的信息 
預覽pem

pem能夠轉換成cer格式,能夠用命令
openssl x509 -in <你的服務器證書>.pem -outform der -out server.cer

也能夠雙擊 cert.pem,這樣是導入到鑰匙串,打開鑰匙串即可導出cer格式的證書。

以上 部分自制證書資料參考的是stackoverflow的這個問題

關於Security框架

看了一下蘋果的官方文檔,Security框架是C語言寫的,提供了一些管理標識碼,證書,數字簽名,信任等的API。 
這裏介紹一下幾個經常使用的對象。SecIdentityRef 代碼一個標識碼對象,struct類型,包含一個SecKeyRef類型和一個SecCertificateRef類型。SecKeyRef就是一個非對稱的key對象。SecCertificateRef是一個遵循X.509標準的證書對象。若是這兩個對象沒有存儲到keychain中,則會把它們轉換成SecKeychainItemRef對象還會使Keychain Services的函數返回錯誤。

要生成p12證書,這讓我想起配置推送證書的時候,導出證書的時候即是把cer格式的證書轉換成p12格式的證書。

iOS實現HTTPS傳輸

由於項目都是用AFN,因此就大概說下AFN的實現方法 
若是是CA認證的證書,則直接用AFN請求即可。

AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

//allowInvalidCertificates 是否容許無效證書(也就是自建的證書),默認爲NO
//若是是須要驗證自建證書,須要設置爲YES
securityPolicy.allowInvalidCertificates = YES;

//validatesDomainName 是否須要驗證域名,默認爲YES;
//假如證書的域名與你請求的域名不一致,需把該項設置爲NO;如設成NO的話,即服務器使用其餘可信任機構頒發的證書,也能夠創建鏈接,這個很是危險,建議打開。
//置爲NO,主要用於這種狀況:客戶端請求的是子域名,而證書上的是另一個域名。由於SSL證書上的域名是獨立的,假如證書上註冊的域名是www.google.com,那麼mail.google.com是沒法驗證經過的;固然,有錢能夠註冊通配符的域名*.google.com,但這個仍是比較貴的。
//如置爲NO,建議本身添加對應域名的校驗邏輯。
securityPolicy.validatesDomainName = YES;

  

若是是自制證書,則客戶端須要導入服務端的公鑰,把公鑰拖進Xocde裏,這裏要用到把證書從pem轉換成p12格式,參見上面的方法 
2.修改驗證方式

- (void)testClientCertificate {
  SecIdentityRef identity = NULL;
  SecTrustRef trust = NULL;
  NSString *p12 = [[NSBundle mainBundle] pathForResource:@"testClient" ofType:@"p12"];
  NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];

  [[self class] extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data];

  NSString *url = @"https://218.244.131.231/ManicureShop/api/order/pay/%@";
  NSDictionary *dic = @{@"request" : @{
                            @"orderNo" : @"1409282102222110030643",
                            @"type" : @(2)
                            }
                        };

  _signString = nil;
  NSData *postData = [NSJSONSerialization dataWithJSONObject:dic
                                                     options:NSJSONWritingPrettyPrinted
                                                       error:nil];
  NSString *sign = [self signWithSignKey:@"test" params:dic];
  NSMutableData *body = [postData mutableCopy];
  NSLog(@"%@", [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]);
  url = [NSString stringWithFormat:url, sign];

  AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
  manager.requestSerializer = [AFJSONRequestSerializer serializer];
  manager.responseSerializer = [AFJSONResponseSerializer serializer];
  [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
  [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
  manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json",
                                                                            @"text/plain"]];
  manager.securityPolicy = [self customSecurityPolicy];

  [manager POST:url parameters:dic success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

    NSLog(@"Error: %@", error);
  }];
}

// 下面這段代碼是處理SSL安全性問題的:
/**** SSL Pinning ****/
- (AFSecurityPolicy*)customSecurityPolicy {
  NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"testClient" ofType:@"cer"];
  NSData *certData = [NSData dataWithContentsOfFile:cerPath];
  AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
  [securityPolicy setAllowInvalidCertificates:YES];
  [securityPolicy setPinnedCertificates:@[certData]];
  [securityPolicy setSSLPinningMode:AFSSLPinningModeCertificate];
  /**** SSL Pinning ****/
  return securityPolicy;
}

  

這段代碼來自參考資料3,寫的很好,不必再說一次了

總結

在如今網絡愈來愈發達的狀況下,安全性愈來愈重要。很少說,https是趨勢。

參考資料: 
1.聊聊 iOS 中的網絡加密 / 滕先洪

2.iOS安全系列之一:HTTPS / Jaminzzhang

3.iOS訪問HTTPS SSL和TLS雙向加密 / 標哥的技術博客

4.蘋果相關官方文檔

相關文章
相關標籤/搜索