Base64
參考站点:http://zh.wikipedia.org/wiki/Base64
简单介绍
是网络上使用最广泛的编码系统,能够将不论什么二进制数据,转换成仅仅有 65 个字符组成的文本文件
a~z,A~Z,0~9,+,/,=
Base 64 编码后的结果能够反算,不够安全
Base 64 是全部现代加密算法的基础算法
终端命令
# 将 10.jpg 进行 base64 编码,生成 10.txt 文件
$ base64 10.jpg -o 10.txt
# 将 10.txt 解码生成 1.jpg 文件
$ base64 -D 10.txt -o 1.jpg
# 将字符串 Man 进行 base64 编码
$ echo -n "Man" | base64
# 将字符串 TWFu 解码
$ echo -n "TWFu" | base64 -D
代码实现
/// BASE 64 编码
- (NSString *)base64Encode:(NSString *)str {
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
return [data base64EncodedStringWithOptions:0];
}
/// BASE 64 解码
- (NSString *)base64Decode:(NSString *)str {
NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:0];
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
保存 和 载入用户信息
/// 保存用户信息
- (void)saveUserInfo {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.usernameText.text forKey:HMUserNameKey];
NSString *pwd = [self base64Encode:self.pwdText.text];
[defaults setObject:pwd forKey:HMUserPwdKey];
[defaults synchronize];
}
/// 载入用户信息
- (void)loadUserInfo {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.usernameText.text = [defaults objectForKey:HMUserNameKey];
self.pwdText.text = [self base64Decode:[defaults objectForKey:HMUserPwdKey]];
}
存在的问题
使用 Base 64 不能直接看到用户password的明文
可是 Base 64 的算法是公开的,而且算法可逆。所以安全性并不好
password学
现代password学 - 全部加密算法都是公开的!
散列(哈希)函数
MD5/SHA1/SHA256(美国国家安全局/苹果)/SHA512
对随意一个二进制数据进行加密,能够得到定长的字符串结果
MD5 加密结果是 32 个字符
核心思想是从给定的数据中。抽取特征码,不easy产生反复。加密后的字符串通常被称为“指纹”“信息摘要”
MD5 由于数据长度不够,如今国外基本上已经不怎么用了!
国内用的非常普遍
王小云
破解站点:http://www.cmd5.com
同样的字符串,使用同样的算法,每次加密的结果是固定的
MD5
约定
同样的password。同样的加密算法,每次加密的结果是不一样
方案一 直接 MD5
pwd = pwd.md5String;
方案二 MD5 + 盐
pwd = [pwd stringByAppendingString:salt].md5String;
MD5 安全方案三 - HMAC
pwd = [pwd hmacMD5StringWithKey:@"haliluya"];
MD5 安全方案四 - 时间戳password
pwd = [self timePassword];
/// 生成时间戳password
- (NSString *)timePassword {
// 1. 以 suday.md5 作为 hmac key
NSString *key = @"sunday".md5String;
NSLog(@"HMAC KEY - %@", key);
// 2. 对用户password HMAC 加密
NSString *pwd = [self.pwd hmacMD5StringWithKey:key];
// 3. 取出当前系统时间
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd HH:mm";
NSString *dateStr = [fmt stringFromDate:[NSDate date]];
// 4. 拼接时间字符串
pwd = [pwd stringByAppendingString:dateStr];
// 5. 再次 hmac 散列password
return [pwd hmacMD5StringWithKey:key];
}
MD5 安全方案五 - server时间戳password
/// 生成时间戳password
- (NSString *)timePassword:(NSString *)pwd {
// 1. 以 itheima.md5 作为 hmac key
NSString *key = @"itheima".md5String;
NSLog(@"HMAC KEY - %@", key);
// 2. 对password进行 hamc
NSString *pwd = [self.pwd hmacMD5StringWithKey:key];
// 3. 取server时间
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://localhost/hmackey.php"]];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSString *dateStr = dict[@"key"];
// 4. 拼接时间字符串
pwd = [pwd stringByAppendingString:dateStr];
// 5. 再次 hmac 散列password
return [pwd hmacMD5StringWithKey:key];
}
对称加密算法
加密和解密使用同一个秘钥,加密解密的速度快
适合给大数据进行加密
注意:秘钥的安全性非常重要
使用 RSA 给对称加密算法的秘钥进行加密
非对称加密算法 RSA
使用 公钥 加密,使用 私钥 解密
使用 私钥 加密,使用 公钥 解密
更安全
可是加密解密的速度极慢!
适合给小数据进行加密
对称加密算法 - 传统加密算法
加密和解密使用同一个密钥
优缺点
长处
算法公开、计算量小、加密速度快、加密效率高
缺点
两方使用同样钥匙,安全性得不到保证
注意事项
密钥的保密工作非常重要
密钥要求定期更换
经典算法
- DES 数据加密标准(用的少。由于强度不够)
- 3DES 使用3个密钥。对同样的数据运行三次加密,强度增强
- AES 高级加密标准,眼下美国国家安全局使用的
- 苹果的钥匙串訪问採用的是 AES 加密
ECB & CBC
ECB :电子代码本,就是说每一个块都是独立加密的
CBC :password块链,使用一个密钥和一个初始化向量 (IV)对数据运行加密转换
OpenSSL 终端測试命令
ECB
# 加密
$ openssl enc -des-ecb -K 616263 -nosalt -in msg1.txt -out msg1.bin
# 解密
$ openssl enc -des-ecb -K 616263 -nosalt -in msg1.bin -out msg1.txt -d
# 查看加密之后的二进制文件
$ xxd msg1.bin
CBC
# 加密
$ openssl enc -des-cbc -K 616263 -iv 0000000000000000 -nosalt -in a.txt -out msg1.bin
# 解密
$ openssl enc -des-cbc -K 616263 -iv 0000000000000000 -nosalt -in msg1.bin -out msg4.txt -d
# 查看加密之后的二进制文件
$ xxd msg1.bin
CBC加密能够有效地保证密文的完整性,也就是说假设有一个块在传送时丢失了(或被敌人改变了),就会导致后面全部的块无法正常解密这个特性能够用来防范一些窃听技巧
代码演示样例:
// EBC 加密
NSLog(@"%@", [CryptorTools AESEncryptString:@"hello" keyString:@"abc" iv:nil]);
NSLog(@"%@", [CryptorTools AESDecryptString:@"d1QG4T2tivoi0Kiu3NEmZQ==" keyString:@"abc" iv:nil]);
// CBC 加密
uint8_t iv[8] = {1, 2, 3, 4, 5, 6, 7, 8};
NSData *ivData = [NSData dataWithBytes:iv length:8];
NSLog(@"%@", [CryptorTools AESEncryptString:@"hello" keyString:@"abc" iv:ivData]);
NSLog(@"%@", [CryptorTools AESDecryptString:@"u3W/N816uzFpcg6pZ+kbdg==" keyString:@"abc" iv:ivData]);
OpenSSL 终端測试命令
ECB 加密/解密
# AES(ECB)加密
$ echo -n "hello" | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
# AES(ECB)解密
$ echo -n "d1QG4T2tivoi0Kiu3NEmZQ==" | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt -d
CBC 加密/解密
# AES(CBC)加密
$ echo -n "hello" | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
AES(CBC)解密
$ echo -n "u3W/N816uzFpcg6pZ+kbdg==" | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -d
终端命令说明
加密过程是先加密,再base64编码
解密过程是先base64解码,再解密
| 是终端管道命令,会将前一个命令结果传递给后一个命令
-K 使用的密钥须要是密钥的 ASCII 码
非对称加密算法
介绍
非对称加密算法须要两个密钥:公开密钥(publickey) 和 私有密钥(privatekey)
公开密钥与私有密钥是一对,假设用公开密钥对数据进行加密,仅仅实用相应的私有密钥才干解密;假设用私有密钥对数据进行加密。那么仅仅实用相应的公开密钥才干解密
特点
算法强度复杂、安全性依赖于算法与密钥
加密解密速度慢
与对称加密算法的对照
- 对称加密仅仅有一种密钥,而且是非公开的,假设要解密就得让对方知道密钥
- 非对称密钥体制有两种密钥,当中一个是公开的
RSA 算法原理
找出两个“非常大”的质数:P & Q
N = P * Q
M = (P – 1) * (Q – 1)找出整数E。E与M互质,即除了1之外,没有其它公约数
找出整数D,使得 ED 除以 M 余 1,即 (E D) % M = 1
经过上述准备工作之后。能够得到:
- E是公钥,负责加密
- D是私钥。负责解密
- N负责公钥和私钥之间的联系
加密算法,假定对X进行加密
- (X ^ E) % N = Y
解密算法,依据费尔马小定义,能够使用下面公式完毕解密
- (Y ^ D) % N = X
代码演示样例:
CryptorTools *tools = [[CryptorTools alloc] init];
// 1. 载入公钥
NSString *pubKeyPath = [[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil];
[tools loadPublicKeyWithFilePath:pubKeyPath];
// 2. 使用公钥加密数据
NSString *cipher = [tools RSAEncryptString:@"abcdefghijklmnopqrstuvwxyz1234567890"];
NSLog(@"%@", cipher);
// 3. 载入私钥
NSString *privateKeyPath = [[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil];
[tools loadPrivateKey:privateKeyPath password:@"123"];
// 4. 解密数据
NSLog(@"%@", [tools RSADecryptString:cipher]);
iOS 相关函数
- SecKeyEncrypt 使用公钥对数据加密
- SecKeyDecrypt 使用私钥对数据解密
- SecKeyRawVerify 使用公钥对数字签名进行验证
- SecKeyRawSign 使用私钥生成数字签名
应用场景
由于RSA算法的加密解密速度要比对称算法的速度慢非常多,在实际应用中,通常採取:
- 数据本身的加密解密使用对称加密算法(AES)
- 用RSA算法加密并传输对称算法所需的密钥
终端測试命令
##程序开发证书生成
# 生成私钥
$ openssl genrsa -out private.pem 1024
# 创建证书请求
$ openssl req -new -key private.pem -out rsacert.csr
# 生成证书并签名,有效期10年
$ openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
# 转换格式-将 PEM 格式文件转换成 DER 格式
$ openssl x509 -outform der -in rsacert.crt -out rsacert.der
# 导出P12文件
$ openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt
在苹果开发中,不能直接使用 PEM 格式的证书
- DER 文件是 CRT 文件的 BASE 64 解码前的二进制数据文件*
- OpenSSL 默认生成的都是 PEM 格式的证书(BASE64 编码后的文本文件)
数字签名
发送方
- ”报文” HASH 得到 “报文摘要”
- “报文摘要” 用公钥加密(数字签名) + 报文
发送给接收方
- 接收方
- “报文” HASH 得到 “报文摘要”
- “数字签名” 用私钥解密 推断是否与 “报文摘要” 同样
生成密钥演示样例
私钥 & 公钥
# 生成强度是 512 的 RSA 私钥
$ openssl genrsa -out private.pem 512
# 以明文输出私钥内容
$ openssl rsa -in private.pem -text -out private.txt
# 校验私钥文件
$ openssl rsa -in private.pem -check
# 从私钥中提取公钥
$ openssl rsa -in private.pem -out public.pem -outform PEM -pubout
# 以明文输出公钥内容
$ openssl rsa -in public.pem -out public.txt -pubin -pubout -text
加密 & 解密
# 使用公钥加密小文件
$ openssl rsautl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.bin
# 使用私钥解密小文件
$ openssl rsautl -decrypt -inkey private.pem -in msg.bin -out a.txt
格式转换
# 将私钥转换成 DER 格式
$ openssl rsa -in private.pem -out private.der -outform der
# 将公钥转换成 DER 格式
$ openssl rsa -in public.pem -out public.der -pubin -outform der
PKCS
Public-Key Cryptography Standards (PKCS)是由美国 RSA 数据安全公司及其合作伙伴制定的一组公钥password学标准,当中包含证书申请、证书更新、证书作废表公布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议
PKCS协议
协议 <->说明
- PKCS#1 定义 RSA 公开密钥算法加密和签名机制。主要用于组织 PKCS#7 中所描写叙述的数字签名和数字信封(专门用来加密/解密)
- PKCS#8 描写叙述私有密钥信息格式,该信息包含公开密钥算法的私有密钥以及可选的属性集等(JAVA使用)
- PKCS#12 描写叙述个人信息交换语法标准。描写叙述了将用户公钥、私钥、证书和其它相关信息打包的语法(苹果使用)