参考网站: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 不能直接看到用户密码的明文
但是 Base 64 的算法是公开的,并且算法可逆,所以安全性并不好
现代密码学 - 所有加密算法都是公开的!
MD5/SHA1/SHA256(美国国家安全局/苹果)/SHA512
对任意一个二进制数据进行加密,可以得到定长的字符串结果
MD5 加密结果是 32 个字符
核心思想是从给定的数据中,抽取特征码,不容易产生重复!加密后的字符串通常被称为“指纹”“信息摘要”
MD5 因为数据长度不够,现在国外基本上已经不怎么用了!国内用的很普遍
王小云
破解网站:http://www.cmd5.com
相同的字符串,使用相同的算法,每次加密的结果是固定的
同样的密码,同样的加密算法,每次加密的结果是不一样
pwd = pwd.md5String;
pwd = [pwd stringByAppendingString:salt].md5String;
pwd = [pwd hmacMD5StringWithKey:@"haliluya"];
pwd = [self timePassword];
/// 生成时间戳密码
- (NSString *)timePassword {
// 1. 以 suday.md5 作为 hmac key
NSString *key = @"sunday".md5String;
NSLog(@"HMAC KEY - %@", key);
// 2. 对用户密码 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 散列密码
return [pwd hmacMD5StringWithKey:key];
}
/// 生成时间戳密码
- (NSString *)timePassword:(NSString *)pwd {
// 1. 以 itheima.md5 作为 hmac key
NSString *key = @"itheima".md5String;
NSLog(@"HMAC KEY - %@", key);
// 2. 对密码进行 hamc
NSString *pwd = [self.pwd hmacMD5StringWithKey:key];
// 3. 取服务器时间
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 散列密码
return [pwd hmacMD5StringWithKey:key];
}
加密和解密使用同一个秘钥,加密解密的速度快
适合给大数据进行加密
注意:秘钥的安全性非常重要
使用 RSA 给对称加密算法的秘钥进行加密
使用 公钥 加密,使用 私钥 解密
使用 私钥 加密,使用 公钥 解密
更安全
但是加密解密的速度极慢!
适合给小数据进行加密
加密和解密使用同一个密钥
算法公开、计算量小、加密速度快、加密效率高
双方使用相同钥匙,安全性得不到保证
密钥的保密工作非常重要
密钥要求定期更换
ECB :电子代码本,就是说每个块都是独立加密的
CBC :密码块链,使用一个密钥和一个初始化向量 (IV)对数据执行加密转换
OpenSSL 终端测试命令
# 加密
$ 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
# 加密
$ 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 终端测试命令
# 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
# AES(CBC)加密
$ echo -n "hello" | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
$ echo -n "u3W/N816uzFpcg6pZ+kbdg==" | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -d
加密过程是先加密,再base64编码
解密过程是先base64解码,再解密
| 是终端管道命令,会将前一个命令结果传递给后一个命令
-K 使用的密钥需要是密钥的 ASCII 码
非对称加密算法需要两个密钥:公开密钥(publickey) 和 私有密钥(privatekey)
公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密
算法强度复杂、安全性依赖于算法与密钥
加密解密速度慢
找出两个“很大”的质数:P & Q
N = P * Q
M = (P – 1) * (Q – 1)
找出整数E,E与M互质,即除了1之外,没有其他公约数
找出整数D,使得 ED 除以 M 余 1,即 (E D) % M = 1
经过上述准备工作之后,可以得到:
加密算法,假定对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]);
由于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 格式的证书
发送方
发送给接收方
# 生成强度是 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
Public-Key Cryptography Standards (PKCS)是由美国 RSA 数据安全公司及其合作伙伴制定的一组公钥密码学标准,其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议
协议 <->说明
原文地址:http://blog.csdn.net/liulanghk/article/details/46405245