Supplementary session behind https

由于ios9之后强制的https请求,原来的http请求所占的市场比率也越来越小。在网上查了几十篇类似的https请求的文章,诸如此类的问题很多,但是回答者含糊其辞, 都不尽如人意,经过几天的探索,写下这篇文章,希望可以帮到有这方便需求的开发者。
首先,需要知道什么是https,以此共勉。
1.HTTPS和HTTP的区别

https协议需要到CA申请证书,一般免费证书很少,需要交费。
http是超文本传输协议,信息是明文传输,https则是具有安全性的SSL加密传输协议。
http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

2.非对称加密算法

  这种加密或许理解起来比较困难,这种加密指的是可以生成公钥和私钥。凡是公钥加密的数据,公钥自身不能解密,而需要私钥才能解密;凡是私钥加密的数据,私钥不能解密,需要公钥才能解密。这种算法事实上有很多,常用的是RSA,其基于的数学原理是两个大素数的乘积很容易算,而拿到这个乘积去算出是哪两个素数相乘就很复杂了,具体原理有兴趣可以自行研究。

Asymmetric encryption is more secure compared to symmetric encryption, but there are two obvious shortcomings:

CPU计算资源消耗非常大。一次完全TLS握手,密钥交换时的非对称解密计算量占整个握手过程的90%以上。而对称加密的计算量只相当于非对称加密的0.1%,如果应用层数据也使用非对称加解密,性能开销太大,无法承受。
非对称加密算法对加密内容的长度有限制,不能超过公钥长度。比如现在常用的公钥长度是2048位,意味着待加密内容不能超过256个字节。

Plus it can only be used for public key encryption key exchange or signature content, not suitable for the application layer to transfer content decryption.
3 Authentication (CA digital certificate)

After the https protocol authentication part is done by a digital certificate, a public key certificate, the certificate subject, digital signatures and other content composition, the client initiates SSL requests, the server will send the client digital certificate, the client the certificate is verified and acquires a secret key of an asymmetric key exchange.

Digital certificate serves two purposes:

身份授权。确保浏览器访问的网站是经过CA验证的可信任的网站。
分发公钥。每个数字证书都包含了注册者生成的公钥。在SSL握手时会通过certificate消息传输给客户端。

Apply for a digital certificate trusted usually the following process:

终端实体(可以是一个终端硬件或者网站)生成公私钥和证书请求。
RA(证书注册及审核机构)检查实体的合法性。如果个人或者小网站,这一步不是必须的。
CA(证书签发机构)签发证书,发送给申请者。
证书更新到repository(负责数字证书及CRL内容存储和分发),终端后续从repository更新证书,查询证书状态等。 

Well, ado, on the code.
First of all: If it is a two-way certificate authentication, you need to import the server, ASI I do not know how to do, but need to create a new category AFN
- (AFSecurityPolicy *) customSecurityPolicy {

NSString *cerPath = [[NSBundle mainBundle] pathForResource:fuwuqi ofType:];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
[securityPolicy setAllowInvalidCertificates:YES];
[securityPolicy setPinnedCertificates:@[certData]];
/**** SSL Pinning ****/
return securityPolicy;

} Ps: This class does not actually build capital does not matter, but must first be created before the request out of this securityPolicy

All requests are returned by the server in - (void) connection: (NSURLConnection *) connection

willSendRequestForAuthenticationChallenge: (NSURLAuthenticationChallenge *) challenge
to authenticate this method, it is necessary to override this method

NSString *thePath = [[NSBundle mainBundle] pathForResource:kehuduan ofType:];

NSLog(@"thePath===========%@",thePath);

NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];

CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;



SecIdentityRef identity = NULL;

// extract the ideneity from the certificate

[self extractIdentity :inPKCS12Data :&identity];



SecCertificateRef certificate = NULL;

SecIdentityCopyCertificate (identity, &certificate);



const void *certs[] = {certificate};

//                        CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);

// create a credential from the certificate and ideneity, then reply to the challenge with the credential

//NSLog(@"identity=========%@",identity);

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:NSURLCredentialPersistencePermanent];



//           credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];



[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];

}

Also in this class you need to add a client authentication method OSStatus securityError = errSecSuccess;

CFStringRef password = CFSTR("123456");

const void *keys[] = { kSecImportExportPassphrase };

const void *values[] = { password };



CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);



CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

securityError = SecPKCS12Import(inP12Data, options, &items);



if (securityError == 0)

{

    CFDictionaryRef ident = CFArrayGetValueAtIndex(items,0);

    const void *tempIdentity = NULL;

    tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity);

    *identity = (SecIdentityRef)tempIdentity;

}



if (options) {

    CFRelease(options);

}



return securityError;

Such a certificate will be returned by the server and, compared with the certificate by the local public key to decrypt, then continue to the next step, to generate a validation check, carry local client certificate to the server, server to verify if this is the way authentication through . Of course, there are the self-signed certificate is used, if it is purchased CA certificates, you do not need to verify
securityPolicy that step, and
we welcome comments.

Guess you like

Origin blog.csdn.net/HflyDragon/article/details/50633607