iOS 开发之网络数据安全
网络安全原则
安全的原则
1)在
网络
上不允许
传输用户隐私数据的明文
。
2)在本地不允许保存用户隐私数据的明文
。
请求方法
1.一定要使用
POST请求
提交用户的隐私数据
。
2.GET请求
的所有参数
都直接暴露在URL中
。
3.请求的URL
一般会记录在服务器
的访问日志中。
4.服务器的访问日志
是黑客攻击
的重点对象之一
。
用户的隐私数据
登录密码
银行账号
… …
数据安全
数据拦截(抓包工具)
1.仅仅用
POST请求
提交用户的隐私数据
,还是不能完全解决安全问题。
2.可以利用软件(比如Charles)
设置代理服务器,拦截查看手机的请求数据。
3.因此:提交用户的隐私数据
时,一定不要明文提交
,要加密处理后
再提交
。
信息安全所面临的威胁
data.png1.机密性(被窃听,秘密泄露)。
2.完整性(篡改,信息被修改)。
3.认证(伪装,伪装成通信双方)。
4.不可否认性(否认,事后不承认是自己发送的)。
-
常用的加密算法
及加密算法的选择
1.
MD5 \ SHA \ DES \ 3DES \ RC2和RC4 \ RSA \ IDEA \ DSA \ AES
。
2.一般公司都会有一套自己的加密方案,按照公司接口文档的规定去加密
。
Base64编码
- 说明
1.HTTP将Base64编码用于基本的认证和摘要认证。
2.其可以方便的将用户的任何输入转换成只包含特定字符的安全格式,服务于网络通信过程。
- 命令行进行
Base64编码
和解码
。
base64.png
编码
:base64 123.png -o 123.txt
解码
:base64 123.txt -o test.png -D
- 特点
1.可以将
任意的二进制数据
进行Base64编码
。
2.所有的数据
都能被编码
为并只用65个字符
就能表示的文本文件
。
3.编码后
的65个字符
包括A~Z,a~z,0~9,+,/,=
。
4.对文件
或字符串
进行Base64编码后
将比原始大小增加33%
。
5.能够逆运算
。
6.不够安全
,但却被很多加密算法作为编码方式
。
-
Base64
编码原理:
1、将所有字符转化为
ASCII码
;
2、将ASCII码
转化为8位
二进制;
3、将二进制3
个归成一组(不足3
个在后边补0
)共24
位,再拆分成4
组,每组6
位;
4、统一在6
位二进制前补两个0凑足
8位; 5、将补
0`后的二进制转为十进制;
6、从Base64编码表获取十进制对应的Base64编码;
处理过程说明:
a、转换的时候,将`3个byte的数据`,先后放入`1个24bit的缓冲区中`,先来的`byte`占高位。
b、数据不足`3byte`的话,于缓冲区中剩下的bit用`0`补足。然后,`每次`取出`6个bit`,按照其值选择查表选择对应的字符作为编码后的输出。
c、不断进行,直到全部输入数据转换完成。
d、如果最后剩下两个输入数据,在编码结果后加`1`个“=”;
e、如果最后剩下一个输入数据,编码结果后加`2`个“=”;
f、如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。
- 实现
a.说明:
1)从iOS7.0 开始,苹果就提供了base64的编码和解码支持
2)如果是老项目,则还能看到base64编码和解码的第三方框架,如果当前不再支持iOS7.0以下版本,则建议替换。
b.相关代码:
//给定一个字符串,对该字符串进行Base64编码,然后返回编码后的结果
-(NSString *)base64EncodeString:(NSString *)string
{
//1.先把字符串转换为二进制数据
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
//2.对二进制数据进行base64编码,返回编码后的字符串
return [data base64EncodedStringWithOptions:0];
}
//对base64编码后的字符串进行解码
-(NSString *)base64DecodeString:(NSString *)string
{
//1.将base64编码后的字符串『解码』为二进制数据
NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:0];
//2.把二进制数据转换为字符串返回
return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
}
c.终端测试命令
$ echo -n A | base64
$ echo -n QQ== |base64 -D
- 常见的安全处理机制
单向散列函数:
MD5 | SHA1 | SHA256 | SHA512
等。
消息认证码:HMAC-MD5 | HMAC-SHA1
。
对称加密:DES | 3DES | AES(高级加密标准)
。
非对称加密:RSA
。
数字签名
证书
- 对消息加密解密的
两种
处理方式:
1)只需要保存一个值,保证该值的机密性,而不需要知道原文。
2)除了保证机密性外还需要对该值进行解密得到消息原文。
- 单向散列函数
- 性质
1)对任意长度的消息散列得到散列值是定长的。
2)散列计算速度快,非常高效。
3)消息不同,则散列值一定不同。
4)消息相同,则散列值一定相同。
5)具备单向性,无法逆推计算。
- 说明
1.单向散列函数
也称为消息摘要函数
、哈希函数
或者函数
。
2.单向散列函数输出的散列值
又称为消息摘要
或者指纹
。
singe.png
- 经典算法
MD4
、MD5
、SHA1
、SHA256
、SHA512
等。
- MD5
MD5
简单说明:
1.MD5
是由Rivest
于1991年设计的单向散列函数
。
2.全称是Message Digest Algorithm 5
,译为“消息摘要算法第5版”
。
MD5
的特点:
1.对输入信息
生成唯一
的128位散列值(32个字符)
。
2.明文
不同,则散列值一定不同
。
3.明文
相同,则散列值一定相同
。
4.根据输出值
,不能得到原始的明文
,即其过程不可逆
。
MD5
的应用
1.加密
。
2.搜索
。
3.文件完整性验证
。
- 安全性
1)MD5
解密网站:http://www.cmd5.com
2)MD5
的强抗碰撞性已经被证实攻破,即对于重要数据不应该再继续使用MD5加密
。
-
提交
register.png隐私数据的安全过程
–注册
-
提交
login.png隐私数据的安全过程
–登录
-
结论:
1.用户的隐私数据,只有在用户输入那一刻是明文,其他情况都是密文处理
。
2.注册只需要将密码明文加密过后,保存到数据库中,在登录时,将加密之后的密文和数据库中的密文进行比较(不需要对密文解密),相同则返回登录成功
。 -
MD5
改进
- 现在的MD5已不再是绝对安全,对此,可以对MD5稍作改进,以增加解密的难度:
1、加盐(Salt)
:在明文的固定位置插入随机串,然后再进行MD5。
2、先加密,后乱序
:先对明文进行MD5,然后对加密得到的MD5串的字符进行乱序。
3、先乱序,后加密
:先对明文字符串进行乱序处理,然后对得到的串进行加密。
4、先乱序,再加盐,再MD5
等。
5、总之宗旨就是
:黑客就算攻破了数据库,也无法解密出正确的明文。
- 加密命令行
MD5加密-字符串 $ echo -n "520it" |md5
MD5加密-文件1 $ md5 abc.png
SHA1加密: $ echo -n "520it" |openssl sha -sha1
SHA256 $ echo -n "520it" |openssl sha -sha256
SHA512 $ echo -n "520it" |openssl sha -sha512
hmacMD5加密 $ echo -n "520it" |openssl dgst -md5 -hmac "123"
-
散列函数应用领域
1)搜索 多个关键字,先对每个关键字进行散列,然后多个关键字进行或运算,如果值一致则搜索结果一致
2)版权 对文件进行散列判断该文件是否是正版或原版的
3)文件完整性验证 对整个文件进行散列,比较散列值判断文件是否完整或被篡改 -
消息认证机制(HMAC)
简单说明-
1、原理
①消息的发送者
和接收者
有一个共享密钥
。
②发送者使用共享密钥对消息加密计算得到MAC值(消息认证码)
。
③消息接收者
使用共享密钥对消息加密计算得到MAC值
。
④比较两个MAC值是否一致
。 -
2、使用
①客户端
需要在发送的时候把(消息)+(消息·HMAC)一起发送给服务器
。
②服务器
接收到数据后,对拿到的消息用共享的KEY进行HMAC,比较是否一致,如果一致则信任
。
-
#import "ViewController.h"
#import "NSString+Hash.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// [self md5];
[self hMac];
}
/**
* 方法说明:消息认证码
*/
- (void)hMac{
NSString *string0 = @"520it";
//认证码:先发送网络请求获取认证码
NSString *renzhengCode = @"RENZHENGMA";
//网络请求获取认证码 两次加密处理:先使用认证码来进行加密处理,接着对加密之后的密文进行一次散列计算
NSString *hMacString0 = [string0 hmacMD5StringWithKey:renzhengCode];
//b42299f23989da507afad6fb7ff1e96d
NSLog(@"hMacString0:%@ - %ld",hMacString0,hMacString0.length);
}
/**
* 方法说明:MD5系列加密
*/
- (void)md5{
/**
MD5
用户的输入:520it
加密的原文:520it
发送给服务器的数据:21bfcc4c2625469d8ec6f3d710dcb0fe
可能被拦截的数据:21bfcc4c2625469d8ec6f3d710dcb0fe
可能存在的破解:21bfcc4c2625469d8ec6f3d710dcb0fe -> 520it
*/
NSString *string = @"520it";
NSLog(@"MD5|string:%@",[string md5String]);
/**
MD5 * N
用户的输入:520it
加密的原文:520it
发送给服务器的数据:3e1bc183ec3c95afe85d45483f2d107c
可能被拦截的数据:3e1bc183ec3c95afe85d45483f2d107c
可能存在的破解:3e1bc183ec3c95afe85d45483f2d107c ->21bfcc4c2625469d8ec6f3d710dcb0fe -> 520it
*/
NSString *string1 = @"520it";
NSLog(@"MD5 * N|string1:%@",[[string1 md5String] md5String]);
/**
MD5 + Salt
Salt:要足够的长,足够的复杂
用户的输入:520it
加密的原文:520it
发送给服务器的数据:549345ff7a43d6bcb199832e8013b6df
可能被拦截的数据:549345ff7a43d6bcb199832e8013b6df
可能存在的破解:549345ff7a43d6bcb199832e8013b6df -> 520it123456
用户的输入:kxt
加密的原文:kxt
发送给服务器的数据:510f38957bc2982fafc35d8bf5f712b5
可能被拦截的数据:510f38957bc2982fafc35d8bf5f712b5
可能存在的破解:510f38957bc2982fafc35d8bf5f712b5 -> kxt123456
总结:输入不同的原文解密之后有:520it123456 | kxt123456 通过两次解密结果对比123456为加盐部分去掉:520it | kxt
*/
NSString *salt = @"123456";
NSString *string2 = @"520it";
string2 = [string2 stringByAppendingString:salt];
NSLog(@"MD5 + Salt|string2:%@",[string2 md5String]);
NSString *string3 = @"kxt";
string3 = [string3 stringByAppendingString:salt];
NSLog(@"MD5 + Salt|string3:%@",[string3 md5String]);
/**
先乱序,在加密(安全性很高)
用户的输入:520it 乱序之后得到加密原文 it520
加密的原文:it520
发送给服务器的数据:c1e8a4de626d2dd197cbfea2a3171250
可能被拦截的数据:c1e8a4de626d2dd197cbfea2a3171250
可能存在的破解:c1e8a4de626d2dd197cbfea2a3171250 -> it520
*/
NSString *string4 = @"520it";
NSString *str1 = [string4 substringFromIndex:3];
NSString *str2 = [string4 substringToIndex:3];
string4 = [str1 stringByAppendingString:str2];
NSLog(@"%@-%@-%@",str1,str2,string4);
NSLog(@"先乱序,在加密:%@",[string4 md5String]);
/**
直接对字符串加密,得到32位的字符串,只截取该字符的串的固定长度(一部分)作为密文
用户的输入:520it
加密的原文:520it
加密的密文:21bfcc4c2625469d8ec6f3d710dcb0fe
将加密之后的密文截取固定的长度,发送给服务器如:截取0~13
发送给服务器的数据:21bfcc4c26254
可能被拦截的数据:21bfcc4c26254
可能存在的破解:21bfcc4c26254 -> 21bfcc4c26254(不能使用MD5的方式破解因为MD5是32位的)
*/
//加密的原文
NSString *string5 = @"520it";
//加密之后的密文
NSString *strMD5 = [string5 md5String];
NSLog(@"strMD5:%@",strMD5);
//要发送给服务器的数据:(strMD5:截取0~13)
NSString *sendStr = [strMD5 substringToIndex:13];
NSLog(@"要发送给服务器的数据:%@",sendStr);
}
@end
对称加密
-
- 对称加密的特点
1)
加密/解密
使用相同的密钥
。
2)加密
和解密
的过程是可逆的(明文-》密文-》明文)
。
- 2.经典算法
1)
DES 数据加密标准
2)3DES 使用3个密钥
,对消息进行(密钥1·加密)+(密钥2·解密)+(密钥3·加密)
3)AES 高级加密标准
- 3.分组密码简单说明
密码算法
可以分为分组密码
和流密码
两种:
1)分组密码
:每次只能处理特定长度的一组数据的一类密码算法。一个分组的比特数量就称之为分组长度。
ex:DES和3DES的分组长度都是64比特。即每次只能加密64比特的明文,并生成64比特的密文。AES的分组长度有128比特、192比特和256比特可以选择。
2)流密码
:对数据流进行连续处理的一类算法。流密码中一般以1比特、8比特或者是32比特等作为单位俩进行加密和解密。 - 4.ECB分组模式
ECB
模式的全称为Electronic CodeBook
模式。又成为电子密码本模式
。
特点:
1)使用ECB模式加密的时候,相同的明文分组会被转换为相同的密文分组。
2)类似于一个巨大的明文分组-》密文分组的对照表。
终端测试命令:
加密 $ openssl enc -des-ecb -K 616263 -nosalt -in 123.txt -out 123.bin
解密 $ openssl enc -des-ecb -K 616263 -nosalt -in 123.bin -out 1231.txt -d
- 5.CBC分组模式
CBC.png1.
CBC
模式全称为Cipher Block Chainning
模式(密文分组链接模式|电子密码链条
)。
特点
:在CBC
模式中,首先将明文分组
与前一个密文分组进行异或(XOR)运算
,然后再进行加密
。
c-b-c.png
终端命令:
加密 $ openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -in a.txt -out a.bin
解密 $ openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -in a.bin -out a1.txt -d
#import "ViewController.h"
#import "EncryptionTools.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// [self AES_ECB];
// [self AES_CBC];
[self DES_CBC];
// [self DES_ECB];
}
- (void)DES_CBC{
NSString *string = @"haha";
NSString *keyString = @"abc";
uint8_t iv[8] = {1,2,3,4,5,6,7,8};
NSData *data = [[NSData alloc]initWithBytes:iv length:sizeof(iv)];
[EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
NSLog(@"DES-CBC 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:data]);
NSLog(@"DES-CBC 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"gmVDD4Bj4ZE=" keyString:keyString iv:data]);
}
- (void)DES_ECB{
NSString *string = @"haha";
NSString *keyString = @"abc";
//DES -ECB
[EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES; //设置加密方式为DES
//echo -n "haha" |openssl enc -des-ecb -K 616263 -nosalt |base64
NSLog(@"DES-ECB 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:nil]);
//echo -n "b2Z9CtPer5Y=" |base64 -D |openssl enc -des-ecb -K 616263 -nosalt -d
NSLog(@"DES-ECB 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"b2Z9CtPer5Y=" keyString:keyString iv:nil]);
}
//AES - CBC
- (void)AES_CBC{
NSString *string = @"haha";
NSString *keyString = @"abc";
//AES -CBC
uint8_t iv[8] = {1,2,3,4,5,6,7,8};
NSData *data = [[NSData alloc]initWithBytes:iv length:sizeof(iv)];
// echo -n "haha" |openssl enc -aes-128-cbc -K 616263 -nosalt -iv 0102030405060708 |base64
NSLog(@"AES-CBC 加密:%@",[[EncryptionTools sharedEncryptionTools] encryptString:string keyString:keyString iv:data]);
// echo -n "E/wWqUTiw/E+1DThAzV39A==" |base64 -D |openssl enc -aes-128-cbc -K 616263 -nosalt -iv 0102030405060708 -d
NSLog(@"AES-CBC 解密:%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"E/wWqUTiw/E+1DThAzV39A==" keyString:keyString iv:data]);
}
//AES - ECB
- (void)AES_ECB{
/**
* 参数说明
* 该方法内部会对加密之后的密文进行base64编码
* 第一个参数:要加密的字符串
* 第二个参数:密钥
* 第三个参数:初始向量(只有CBC的时候才用到)
*/
NSString *encryptString = @"haha";
NSString *keyString = @"abc";
NSString *enString = [[EncryptionTools sharedEncryptionTools] encryptString:encryptString keyString:keyString iv:nil];
//AES_ECB:MIoAu+xUEpQZSUmkZUW6JQ==
/**
终端验证:
nanadeMacBook-Pro:~ mac2016$ echo -n "haha" | openssl enc -aes-128-ecb -K 616263 -nosalt |base64
MIoAu+xUEpQZSUmkZUW6JQ==
*/
NSLog(@"AES_ECB加密:%@",enString);
NSString *decryptString=@"MIoAu+xUEpQZSUmkZUW6JQ==";
NSString *deString = [[EncryptionTools sharedEncryptionTools] decryptString:decryptString keyString:keyString iv:nil];
// 终端验证:
// echo -n "MIoAu+xUEpQZSUmkZUW6JQ==" |base64 -D |openssl enc -aes-128-ecb -K 616263 -nosalt -d
NSLog(@"AES_ECB解密:%@",deString);
}
//16进制
abc = 616263
@end
非对称加密
(1)
非对称加密算法
需要两个密钥
:公开密钥
(publickey)和私有密钥
(privatekey)。
(2)公开密钥
与私有密钥
是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密
。
(3)特点:
a、非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快
。
b、对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。
- 1.
非对称加密
的特点:1)使用
公钥加密
,使用私钥解密
;
2)公钥
是公开
的,私钥保密
;
3)加密处理安全
,但是性能极差
。
- 2.
经典算法---RSA
1)
RSA
原理:
(1)求N
,准备两个质数
p和q,N = p x q;
(2)求L
,L
是p-1
和q-1
的最小公倍数
。L = lcm(p-1,q-1)
;
(3)求E
,E
和L
的最大公约数为1
(E和L互质
);
(4)求D
,E x D mode L = 1
。
2)
RSA加密小实践
(1)p = 17,q = 19 =>N = 323
;
(2)lcm(p-1,q-1)=>lcm(16,18)=>L= 144
;
(3)gcd(E,L)=1 =>E=5
;
(4)E
乘以几
可以mode L =1?
D=29
可以满足;
(5)得到公钥为
:E=5,N=323
;
(6)得到私钥为
:D=29,N=323
;
(7)加密 明文
的E
次方mod N = 123的5次方 mod 323 = 225(密文)
;
(8)解密 密文
的D
次方mod N = 225的29次方 mod 323 = 123(明文)
。
3)
openssl
生成密钥命令
(1) 生成强度是 512 的 RSA 私钥:
$ openssl genrsa -out private.pem 512
(2) 以明文输出私钥内容:
$ openssl rsa -in private.pem -text -out private.txt
(3) 校验私钥文件:
$ openssl rsa -in private.pem -check
(4) 从私钥中提取公钥:
$ openssl rsa -in private.pem -out public.pem -outform PEM -pubout
(5) 以明文输出公钥内容:
$ openssl rsa -in public.pem -out public.txt -pubin -pubout -text
(6) 使用公钥加密小文件:
$ openssl rsautl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.bin
(7) 使用私钥解密小文件:
$ openssl rsautl -decrypt -inkey private.pem -in msg.bin -out a.txt
(8) 将私钥转换成 DER 格式:
$ openssl rsa -in private.pem -out private.der -outform der
(9) 将公钥转换成 DER 格式:
$ openssl rsa -in public.pem -out public.der -pubin -outform der
数字签名
1.数字签名的应用场景
答:需要严格验证发送方身份信息情况
数字签名.png2.
数字签名原理
:
1)客户端处理
:
①对"消息"
进行 HASH 得到"消息摘要"
;
②发送方使用自己的私钥对"消息摘要"
加密(数字签名);
③把数字签名附着在"报文"
的末尾一起发送给接收方。
2)服务端处理
:
①对"消息"
HASH 得到"报文摘要"
;
②使用公钥对"数字签名"
解密;
③对结果进行匹配
数字证书
1.简单说明
证书和驾照很相似,里面记有姓名、组织、地址等个人信息,以及属于此人的公钥,并有认证机构施加数字签名,只要看到公钥证书,我们就可以知道认证机构认证该公钥的确属于此人。
2.数字证书的内容
1)公钥
2)认证机构的数字签名
3.证书的生成步骤:
1)生成私钥 :
openssl genrsa -out private.pem 1024
;
2)创建证书请求:
openssl req -new -key private.pem -out rsacert.csr
;
3)生成证书并签名,有效期10年 :
openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
4)将 PEM 格式文件转换成 DER 格式 :
openssl x509 -outform der -in rsacert.crt -out rsacert.der
5)导出P12文件 :
openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt
4.iOS开发中的注意点:
1)在iOS开发中,不能直接使用 PEM 格式的证书
,因为其内部进行了Base64
编码,应该使用的是DER的证书
,是二进制格式的
。
2)OpenSSL
默认生成的都是PEM格式的证书
。
#import "ViewController.h"
#import "RSACryptor.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//使用公钥来进行加密,使用私钥来进行解密
//01 加载公钥
NSString *path = [[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil];
[[RSACryptor sharedRSACryptor] loadPublicKey:path];
//02 对数据加密
NSData *data = [[RSACryptor sharedRSACryptor] encryptData:[@"520it" dataUsingEncoding:NSUTF8StringEncoding]];
//对加密得到的密文进行base64编码
NSString *oo = [data base64EncodedStringWithOptions:kNilOptions];
//Q1RapLxau+1YQmGCo6/QVrTXdfQo+ky7orApyvBi+BlfPOyYylCeVYDIHtXqXPn99caNscU4v1drGDvyoyqQSxEcHi7/F59WerrQ6MgJZF+31VsbDylkew+Cl2cAB4d9I0h+Gp0f2tJEL7oTb7w2bQ/bpo7HrqOeua8hybQgJLI=
NSLog(@"加密:%@",oo);
//03 加载私钥
NSString *path1 = [[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil];
[[RSACryptor sharedRSACryptor] loadPrivateKey:path1 password:@"123456"];
//04 对数据解密
NSData *data1 = [[RSACryptor sharedRSACryptor] decryptData:data];
NSString *oo1 = [[NSString alloc] initWithData:data1 encoding:NSUTF8StringEncoding];
// 520it
NSLog(@"解密%@",oo1);
}
@end
混合密码系统:对称加密 + 非对称加密
先使用非对称加密来完成密钥的交换(后面对称加密需要使用的密钥),后面所有的通信都使用对称加密来完成后面的通信
HTTPS的基本使用
1.
https
简单说明
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer
),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。
https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。
2.
HTTPS
和HTTP
的区别主要为以下四点
:
一、https协议需要到ca申请证书,一般免费证书很少,需要交费。
二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80
,后者是443`。
四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
3.
简单说明
1)HTTPS的主要思想是在不安全的网络上创建一安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理的保护。
2)HTTPS的信任继承基于预先安装在浏览器中的证书颁发机构(如VeriSign、Microsoft等)(意即“我信任证书颁发机构告诉我应该信任的”)。
3)因此,一个到某网站的HTTPS连接可被信任,如果服务器搭建自己的https 也就是说采用自认证的方式来建立https信道,这样一般在客户端是不被信任的。
4)所以我们一般在浏览器访问一些https站点的时候会有一个提示,问你是否继续。
4.对开发的影响。
- 4.1 如果是自己使用
NSURLSession
来封装网络请求,涉及代码如下。
#import "ViewController.h"
@interface ViewController ()<NSURLSessionDataDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
/*
HTTPS请求的时候:
[1] 证书是受信任的,什么都不用做
[2] 证书是不受信任的,是自签名的
(1) 修改配置文件,禁用ATS特性
(2) 信任并安装(数字证书)
*/
//
// 支付宝
/**
NSURL *url = [NSURL URLWithString:@"https://www.alipay.com/"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
[dataTask resume];
*/
// 12306(之前不是ca认证这里仍然使用该网站举例)
NSURL *url = [NSURL URLWithString:@"https://kyfw.12306.cn/otn/"];
NSURLSession *session = [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
[dataTask resume];
}
#pragma---------------------------------------
#pragma MARK - NSURLSessionDataDelegate
/*
challenge:挑战,质询
当我们发送的是一个HTTPS请求的时候就会调用该方法,需要在该方法中处理证书
NSURLAuthenticationMethodServerTrust:服务器信任
HTTP:80
HTTPS:443
*/
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
NSLog(@"%@",challenge.protectionSpace);
/*
NSURLSessionAuthChallengeUseCredential = 0, 使用证书
NSURLSessionAuthChallengePerformDefaultHandling = 1, 忽略证书
NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2, 请求被取消,证书被忽略
NSURLSessionAuthChallengeRejectProtectionSpace = 3, 拒绝
*/
//判断只有当时NSURLAuthenticationMethodServerTrust的时候才安装这个证书
if (![challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
return;
}
//根据服务器中的保护控件的服务器信任,来创建一个认证信息
NSURLCredential *credential = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
@end
- 4.2 如果是自己使用
AFN
来网络请求,涉及代码如下。
#import "ViewController.h"
#import "AFNetworking.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
/**
//证书受信任
//01 创建会话管理者对象
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//修改对响应的序列化方式
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//02 发送请求
[manager GET:@"https://www.alipay.com/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error---%@",error);
}];
*/
//01 创建会话管理者对象
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//修改对响应的序列化方式
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//设置AFN中的安全配置
//01 允许接收无效的证书
manager.securityPolicy.allowInvalidCertificates = YES;
//02 不做域名验证
manager.securityPolicy.validatesDomainName = NO;
//03 修改info.plist文件ATS
//02 发送请求
[manager GET:@"https://kyfw.12306.cn/otn/" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error---%@",error);
}];
}
/**
AFNetworking:中的类AFSecurityPolicy说明:
AFSecurityPolicy,内部有三个重要的属性,如下:
AFSSLPinningMode SSLPinningMode; //该属性标明了AFSecurityPolicy是以何种方式来验证
BOOL allowInvalidCertificates; //是否允许不信任的证书通过验证,默认为NO
BOOL validatesDomainName; //是否验证主机名,默认为YES
"AFSSLPinningMode"枚举类型有三个值,分别是AFSSLPinningModeNone、AFSSLPinningModePublicKey、AFSSLPinningModeCertificate。
"AFSSLPinningModeNone"代表了AFSecurityPolicy不做更严格的验证,"只要是系统信任的证书"就可以通过验证,不过,它受到allowInvalidCertificates和validatesDomainName的影响;
"AFSSLPinningModePublicKey"是通过"比较证书当中公钥(PublicKey)部分"来进行验证,通过SecTrustCopyPublicKey方法获取本地证书和服务器证书,然后进行比较,如果有一个相同,则通过验证,此方式主要适用于自建证书搭建的HTTPS服务器和需要较高安全要求的验证;
"AFSSLPinningModeCertificate"则是直接将本地的证书设置为信任的根证书,然后来进行判断,并且比较本地证书的内容和服务器证书内容是否相同,来进行二次判断,此方式适用于较高安全要求的验证。
如果HTTPS服务器满足ATS默认的条件,而且SSL证书是通过权威的CA机构认证过的,那么什么都不用做。如果上面的条件中有任何一个不成立,那么都只能修改ATS配置。
*/
@end