Base64编码
- 可以将任意的
二进制数据
进行Base64编码 - 被编码的数据只用
65
个字符就能表示成文本文件 - 原理
- 将所有的字符转化成
ASCII
码 - 在将对应的
ASCII
码转为8位二进制 - 然后对
二进制进行归组
,每3
个归为一组,不足3个的补e
,这样变成了24
位,在对其拆分成4
组,每组6
位 - 统一在
6
位二进制前补2个0
组成8位,然后将二进制转为十进制 - 最后在Base64编码表中获取十进制对应的base64编码
- 将所有的字符转化成
编码和解码
- (void)viewDidLoad {
[super viewDidLoad];
//编码
NSLog(@"%@",[self base64EncodeStrng:@"测试"]);
//解码
NSString *base64 = [self base64EncodeStrng:@"测试"];
NSLog(@"----%@",[self base64DecodeStrng:base64]);
}
编码
//编码
- (NSString *)base64EncodeStrng:(NSString *)string {
//1.转化为二进制数据
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
//2.对数据进行编码
return [data base64EncodedStringWithOptions:0];
}
解码
//解码
- (NSString *)base64DecodeStrng:(NSString *)string {
//1.转化为二进制数据
NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
//转化为字符串
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
哈希(散列)函数 加密
- 哈希(散列)函数
- MD5
- SHA1
- SHA256/SHA512
1.散列函数
特点
- 算法是公开的
- 对不同的数据加密,得到的结果是定长的,
MD5
对不同的数据加密,得到的结果都是32个字符长的字符串 - 不能反算
1.1 MD5加密
加盐:就是一段固定的无序的字符和你要加密的字符,拼接在一起
- 注意:固定的
盐
一旦被知道,那么加密的安全系数,就会大大的降低,所以一般加盐
的方式不适用了,
static NSString *str = @"cnwuikjkads";
- (void)viewDidLoad {
[super viewDidLoad];
//加盐:就是一段固定的无序的字符和你要机密的字符,拼接在一起
NSString *md5Str = @"测试";
md5Str = [md5Str stringByAppendingString:str];
NSLog(@"%@",[md5Str md5String]);
//打印结果: 2dcee1e9cbef28254ea01ff0b6f80c62
}
- (NSString *)md5String {
//转为C语言的字符串
const char *str = self.UTF8String;
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
//MD5加密计算
CC_MD5(str, (CC_LONG)strlen(str), buffer);
return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
//转化OC语言的字符串
- (NSString *)stringFromBytes:(uint8_t *)bytes length:(int)length {
NSMutableString *strM = [NSMutableString string];
for (int i = 0; i < length; i++) {
[strM appendFormat:@"%02x", bytes[i]];
}
return [strM copy];
}
1.2SHA1加密
- (NSString *)sha1String {
const char *str = self.UTF8String;
uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(str, (CC_LONG)strlen(str), buffer);
return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
1.3 SHA256/SHA512加密
// SHA256
- (NSString *)sha256String {
const char *str = self.UTF8String;
uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(str, (CC_LONG)strlen(str), buffer);
return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
// SHA512加密
- (NSString *)sha512String {
const char *str = self.UTF8String;
uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(str, (CC_LONG)strlen(str), buffer);
return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}
为了弥补
加盐
被泄露,所以有了HMAC
,它是给定一个密钥
进行2次MD5加密
,这里的密钥
一般是从服务器请求获取
HMAC 散列碰撞 加密
//HMAC加密 key是密钥
- (NSString *)hmacMD5StringWithKey:(NSString *)key {
const char *keyData = key.UTF8String;
const char *strData = self.UTF8String;
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
//转化成OC的字符串
return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
- (NSString *)hmacSHA1StringWithKey:(NSString *)key {
const char *keyData = key.UTF8String;
const char *strData = self.UTF8String;
uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer);
return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
- (NSString *)hmacSHA256StringWithKey:(NSString *)key {
const char *keyData = key.UTF8String;
const char *strData = self.UTF8String;
uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer);
return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
- (NSString *)hmacSHA512StringWithKey:(NSString *)key {
const char *keyData = key.UTF8String;
const char *strData = self.UTF8String;
uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer);
return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}
为了用户登录或者注册的时候,我们保存用户名或者密码,最好不要用
NSUserDefaults
,一般使用钥匙串
保存,就用到一个SSKeychain
钥匙串保存用户密码
在使用SSKeychain
的时候,要先开启
- (IBAction)SaveSSKeyAction:(UIButton *)sender {
//保存账号
NSString *account = @"JC";
[[NSUserDefaults standardUserDefaults] setObject:account forKey:@"account_key"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSString *psd = @"12345";
//保存在钥匙串
//参数一:要保存的密码
//参数二:服务可以自己定义,也可以是APP的标识
//参数三:账号
//参数四:返回的error
BOOL isScu = [SSKeychain setPassword:psd forService:@"com.cc.jc" account:account error:nil];
NSLog(@"%@",isScu == YES ?@"成功":@"失败");
}
- (IBAction)getPsdAction:(UIButton *)sender {
//保存成功
//出去数据
NSString *account = [[NSUserDefaults standardUserDefaults] objectForKey:@"account_key"];
//从钥匙串中取出
NSString *psd = [SSKeychain passwordForService:@"com.cc.jc" account:account];
NSLog(@"%@",psd);
}
对称加密
- 对称加密算法
- DES 数据加密标准
- 3DES :使用3个秘钥,对相同的数据来加密3次,增加安全系数
- AES:这个一般是比较高级的加密,
- 有2种加密的方式
- ECB:把每一个
数据块独立加密
,然后拼接在一起,在解密的时候也是先拆分数据块,然后独立解密数据块 - CBC:加密每一个数据块,都会与上一个数据块之前有联系,
- ECB:把每一个
ECB 数据块 加密
测试对称加密,我们打开
终端
1.进入桌面cd Desktop/
2.查看桌面内容ls
3.想对桌面的某个文件进行编辑vim 100.txt
编辑100.txt文件
openssl enc -des-ecb -K 616263 - nosalt -in 110.txt -out msg1.bin 这个是对称机密的一个命令行,其中
openssl
是一个标准的加密库,enc
是加密方式,-des-ecb
表示是DES加密中的ECB
加密方式,-K 616263
是key对应的16进制的ASII码是ABC
,nosalt
是不加盐,后面是-in 110.txt
对这个文件进行加密,-out msg1.bin
输出加密文件
查看加密
CBC 数据块 加密
- 对
110.txt
CBC数据块加密,
openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -in 110.txt -out msg2.bin
命令行中的-iv
是字面向量
代码创建加密
- 这其中用到一个工具类
EncryptionTools
来完成加密
代码 ECB加密
//ECB加密
- (void)setupECB{
//创建 秘钥
NSString *key = @"ABC";
NSString *ecbStr = @"你好";
//加密之后返回的是一个 base64格式的字符串
NSString *bsae64Str = [[EncryptionTools sharedEncryptionTools] encryptString:ecbStr keyString:key iv:nil];
NSLog(@"ECB:---%@",bsae64Str);
//结果: ECB:---8+0WsGSH5h1bYWE5FQjgYg==
//解密
NSString *decBase64Str = [[EncryptionTools sharedEncryptionTools] decryptString:bsae64Str keyString:key iv:nil];
NSLog(@"解密:---%@",decBase64Str);
//结果:解密:---你好
}
代码 CBC加密
//CBC加密
- (void)setupCBC{
//创建 秘钥
NSString *key = @"ABC";
NSString *ecbStr = @"你好";
//向量
uint8_t iv[8] = {3,4,5,6,7,8,9,0};
NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
//加密之后返回的是一个 base64格式的字符串
NSString *bsae64Str = [[EncryptionTools sharedEncryptionTools] encryptString:ecbStr keyString:key iv:ivData];
NSLog(@"ECB:---%@",bsae64Str);
//打印结果:ECB:---B9Rh6e+m7BhpWGBcAKUZUw==
//解密
NSString *decBase64Str = [[EncryptionTools sharedEncryptionTools] decryptString:bsae64Str keyString:key iv:ivData];
NSLog(@"解密:---%@",decBase64Str);
//打印结果:解密:---你好
}
非对称加密算法(RSA)
公钥
和秘钥
的加密方式,用公钥
加密就得用秘钥
解密,反之用秘钥
加密就得有公钥
解密- 这种加密方式一般在
支付类
的APP使用的比较频繁
前期准备工作
打开
终端
进入桌面cd Desktop/
在桌面上新建一个RSA
文件 用来存储 生成的公钥,秘钥和证书
进入
cd RSA
文件
在使用终端的时候,
psd
来看查看现在所在的文件路径
1. 用命令行 生成私钥
openssl genrsa -out private.pem 512
2. 用命令行 生成公钥
openssl rsa -in private.pem -out public.pem -pubout
cat private.pem
查看秘钥
3. 创建请求证书
- 生成
.csr
文件
openssl req -new -key private.pem -out resacert.csr
在这个过程中 需要填写一些信息
国家名称
Country Name (2 letter code) []: CN
省份
State or Province Name (full name) []: shanghai
上海
Locality Name (eg, city) []:
机构名称
Organization Name (eg, company) []:
单位名称
Organizational Unit Name (eg, section) []:
主机名
Common Name (eg, fully qualified host name) []:
邮箱地址
Email Address []:
密码
A challenge password []:
注意
这个密码
一定要记住!!!!!!!
,因为在加载私钥的时候需要密码输入
4. 把 生成的resacert.csr
证书转化为 数字证书
(reacert.crt)
- 命令行如下:
openssl x509 -req -days 3650 -in reacert.csr -signkey private.pem -out reacert.crt
5. 把数字证书
转化 der证书(二进制)
这样苹果可以识别
-
因为
3和4生成的证书
都是16进制
的 -
命令行如下:
openssl x509 -outform der -in reacert.crt -out reacert.der
6. 把数字证书
转化为p12
文件
openssl pkcs12 -export -out p.p12 -inkey private.pem -in reacert.crt
p生成
p12
文件的名称,-inkey
对应的秘钥是private.pem
7. 获取公钥
和私钥
吧生成的公钥和私钥
拖入工程。----->
使用RSACryptor
这个工具类,来对数据进行加密和解密
加载
公钥和秘钥
~注意!!!!
:在加载私钥时 需要你在创建过程中输入的密码
- (void)viewDidLoad {
[super viewDidLoad];
//获取公钥
NSString *filepath = [[NSBundle mainBundle] pathForResource:@"reacert.der" ofType:nil];
[[RSACryptor sharedRSACryptor] loadPublicKey:filepath];
//y私钥
NSString *privatePath = [[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil];
[[RSACryptor sharedRSACryptor] loadPrivateKey:privatePath password:@"123456"];
}
7. 加密和解密
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//需要加密的字符串
//比如:支付密码
NSData *psdData = [@"123456" dataUsingEncoding:NSUTF8StringEncoding];
NSData *resultData = [[RSACryptor sharedRSACryptor] encryptData:psdData];
NSLog(@"RSA加密的二进制数据:----%@",resultData);
NSString *base64Str = [resultData base64EncodedStringWithOptions:0];
NSLog(@"二进制数据对应的64的字符串:%@",base64Str);
NSData *d_data = [[RSACryptor sharedRSACryptor] decryptData:resultData];
NSString *psd = [[NSString alloc] initWithData:d_data encoding:NSUTF8StringEncoding];
NSLog(@"密码:----%@",psd);
}
- 打印结果: