一、MD5

1.简单说明

MD5:全称是Message Digest Algorithm 5,译为“消息摘要算法第5版”效果:对输入信息生成唯一的128位散列值(32个字符)

2.MD5的特点

(1)对不同的数据加密,得到的结果是定长的,MD5对不同的数据进行加密,得到的结果都是32个字符.
(2)根据输出值,不能得到原始的明文,即其过程不可逆(3)算法具有较好的安全性,而且免费
(4)广泛使用主要运用在数字签名、文件完整性验证以及口令加密等方面

MD5用途

- 口令加密

- 搜索 将几个关键字分别md5,在搜索这几个关键字的时候,不管顺序怎么样,还是会得到大致相同的搜素结果。其实就是将这几个关键字的md5值作一些特殊处理,比如相加。

- 版权 不同的数据 MD5 是不一样的,比如一个视频资源,放到服务器上的时候,会将md5值也放上去保存。如果是盗版的,md5值是不一样的。

3.MD5破解

MD5解密网站:http://www.cmd5.com

4.如何使MD5加密更安全?

现在密码学要求:同样的算法,同样的密码明文,每次的结果不一样(密码有实效性)

第一种方式:加盐(Salt)
在明文的固定位置插入随机串,然后再进行MD5
如果盐是固定的,盐有很多人知道(服务器,前端,客户端),会被泄漏,不安全

static NSString *salt =@"fadsfdbvcxweioa43$^$^$$#@23123124";
NSString* password = [self.passField.text
stringByAppendingString:salt].md5String;

第二种方式:先加密,后乱序
先对明文进行MD5,然后对加密得到的MD5串的字符进行乱序
第三种方式:HMAC
现在使用的比较广泛,安全级别更高,破解难度高。
但还是有风险:每次结果一致,有可能被暴力破解。
黑客模拟网络请求,不需要真实密码,也可以获取登陆权限。

给定一个密钥(这个密钥来自于服务器),对明文进行密钥拼接,并且做"两次散列" -> 得到32位结果。

NSString* password = [self.passField.text
hmacMD5StringWithKey:@"hmackey"];

上面代码 md5 的过程:使用密钥hmackey对密码加密,加密后做md5,得到32位字符串,再次使用 hmackey 加密,再md5

HMAC使用方式 :(登陆注册密码加密)
- 注册时,向服务器索取密钥(key),服务器将密钥和用户的账户对应起来保存在数据库。
- 客户端拿到key后保存在本地(钥匙串保存,登陆的时候需要用到这个key进行加密)
- 切换了新的设备(换手机登录或者登录新的已有账号)
重新找服务器获取key,服务器根据账号给(比如qq,第一次登陆会比较慢,因为不仅要获取key,还要获取聊天信息)
eg: 用户在A设备登陆成功后,再去B设备登陆,B从本地找key找不到,就会找服务器要(如果有密码锁就等待授权,如果没有密码锁,就直接获取),服务器会根据A设备(授权)决定给不给(密码锁,也是根据这个key)

5、生成带时间戳的密码

使用时间戳,目前使用非常广泛
思路:
- 客户端注册时输入账号和原始密码,服务器会返回一个key给客户端
- 服务器将账号,key,以及hmac后的密码(EncryptPass)保存在数据库
- 客户端拿到key后,会将原始密码结合key进行一次hmac运算,生成一个加密后的密码(EncryptPass),加密后的密码再结合当前时间(这个时间要从服务器获取)再做一次md5,生成新的加密密码(finalPass)
- 客户端结合时间生产密码后,会发送请求和服务器上的密码作比较(服务器会用EncryptPass结合服务器当前时间,或者当前时间前一分钟,生产服务器的finalPass,如果这两个时间相同,就登陆成功)
- 这样根据时间来做,就算暴力破解或者模拟登陆,已经过了时效了,密码早已经变了。

(1) ------使用客户端时间生成带时间戳的密码------
(NSString *)timePassword{
//1.设置密钥key
NSString *key = @"itheima".md5String;
//2.使用密钥key对密码进行HMac
NSString *pwd = [self.passField.texthmacMD5StringWithKey:key];
NSLog(@"key = %@",key);
//3.获得当前的系统时间
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
//指定时区,真机通常需要指定时区
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh"];
//设置时间格式
fmt.dateFormat = @"yyyy-MM-dd HH:mm";
//格式化当前时间
NSString *dateStr = [fmt stringFromDate:[NSDate date]];
//4.用密码+ 时间 生成密码
pwd =[pwd stringByAppendingString:dateStr];
//5.返回hmac 结果
return [pwd hmacMD5StringWithKey:key];
}
NSString *password = [self timePassword];
(2) ------使用服务器时间,生成带时间戳的密码-----
(NSString *)timePassword{
//1.设置密钥key
NSString *key = @"itheima".md5String;
//2.对密钥key对密码进行HMac
NSString *pwd = [self.passField.text hmacMD5StringWithKey:key];
//3.获得当前服务器的系统时间
NSURL*url = [NSURL URLWithString:@"[http://localhost/hmackey.php](http://localhost/hmackey.php)"];
//使用同步获取时间(注意:这里要使用同步,确定先获得服务器的时间,后面的代码才能执行)
NSData *timeData = [NSData dataWithContentsOfURL:url];
//反序列化取出时间
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:timeData options:0 error:NULL];
NSString *dateStr = dict[@"key"];
//4.用密码+ 时间 生成密码
pwd =[pwd stringByAppendingString:dateStr];
//5.返回hmac 结果
return [pwd hmacMD5StringWithKey:key];
}

 

注意:要获得服务器时间来对密码进行hmac。
有些人手机上的时间设置会比真实的时间的快5分钟。如果是这样的,就会导致客户端获得的系统时间和服务器获得的系统时间相差几分钟。那就会导致hmac 的结果不一致,无法登录。
网络开发中,不管是网络传输还是在本地都不允许保存用户的明文隐私数据

登陆注册时密码的处理方式:
用户注册的时候服务器对密码进行了加密处理,然后保存在数据库,服务器是不需要知道用户的真实密码的。
登陆的时候客户端使用和服务器相同的加密方式,然后和服务器上加密后的密码比较,来完成登陆。

如果android端和mac端有分歧,可以在mac终端用下面命令来检验。
md5 -s "xxxxxxx"

保存密码的方式:(如果想反算原始密码)
1.NSUserDefaults
2.钥匙串访问
- 苹果的"生态圈",从 iOS7.0.3 版本开放
- 在Mac上能够动态生成复杂密码(AES 加密)
- 如果用户访问网站,记住密码,我们还可以看到记住的密码明文
- 本身的所有接口都是 C 语言的.借助三方库

二. 对称加密

* 加密和解密使用同一个"密钥"
* 密钥的保密工作就非常的重要,密钥会定期更换

经典算法

- DES 数据加密标准(用的比较少,因为强度不够).
- 3DES 使用3个密钥,对相同的数据执行三次加密,强度增强.
- AES 高级加密标准,目前美国国家安全局使用AES加密(钥匙串访问就是使用AES加密)
对称加密有两种加密方式: ECB和CBC

ECB: 电子代码本,就是将一个数据拆分为多块,然后独立加密
CBC: 密码块链,使用一个密钥和一个初始化"向量"对数据执行加密转换,能保证密文的完整性,如果一个数据发生改变,后面所有的数据将会被破坏
向量:某个方向的数量.
现代的密码学都和几何有关!因为几何(包含圆形\椭圆\球体)的变量是有规律的,但是结果是多变的
可以在终端通过命令来测试

//ECB加密
openssl enc -des-ecb -K 616263 -nosalt -in xxx.xxx -out XXX.XXX 
//ECB解密 
openssl enc -des-ecb -K 616263 -nosalt -in xxx.xxx -out XXX.XXX -d 
//查看ECB加密之后的文件
$ xxd xxx.xxx

解释:
-des-ecb : 使用ecb方式加密,
-K : 密钥匙'abc'(注意:616263是16进制的)
-nosalt : 不加盐
-in xxx.xxx : 要加密的文件
-out XXX.XXX : 生成的加密文件
=============================================================================
//cbc方式加密
echo -n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
解释:
echo -n hello :要加密的字符串‘hello’
enc -aes-128-cbc : 使用cbc方式加密
-iv 0102030405060708 :向量是‘12345678’
-K : 密钥匙'abc'(注意:616263是16进制的)
-nosalt : 不加盐
base64 :base64编码

提示:
1> 加密过程是先加密,再base64编码
2> 解密过程是先base64解码,再解密

三. 非对称加密(RSA)

公钥\私钥(用公钥加密,私钥解密或者用私钥加密,公钥解密)