iOS学习-数据加密
网络传输数据需要进行加密。
一、对称算法
1、什么是对称算法
加密和解密都使用相同的密钥
特性:
速度快,适合对大数据加密。
常见的有DES、3DES、AES。最常用的是AES。
2、什么是AES加密
高级加密标准,Advanced Encryption Standard的缩写。AES 是一个分组密码算法,旨在取代 DES 成为广泛使用的标准
3、AES加密原理
image.png4、在iOS中的实现
#pragma mark - 2、对称加密:加密、解密
-(void)aesTest{
NSString *str = @"我是中国人";
NSLog(@"原字符=%@",str);
NSString *str1 = [self aesEncrypt:str] ;
NSLog(@"aes加密后-%@",str1);
NSString *str2 = [self aesDecrypt:str1];
NSLog(@"aes解密后-%@",str2);
}
/*
需要导入头文件
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCrypto.h>
*/
// 秘钥key
const NSString *AESKey = @"chsiahGHBh";
-(NSString *)aesEncrypt:(NSString *)sourceStr{
if (!sourceStr){
return nil;
}
char keyPtr[kCCKeySizeAES256];
bzero(keyPtr, sizeof(keyPtr));
[AESKey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSData *sourceData = [sourceStr dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger dataLength = [sourceData length];
size_t buffersize = dataLength+kCCBlockSizeAES128;
void *buffer = malloc(buffersize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [sourceData bytes], dataLength, buffer, buffersize, &numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
NSData *encryptData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
//对加密后的二进制数据进行base64转码
return [encryptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
} else {
free(buffer);
return nil;
}
}
-(NSString *)aesDecrypt:(NSString *)secretStr{
if (!secretStr) {
return nil;
}
//先对加密的字符串进行base64解码
NSData *decodeData = [[NSData alloc] initWithBase64EncodedString:secretStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
char keyPtr[kCCKeySizeAES256 + 1];
bzero(keyPtr, sizeof(keyPtr));
[AESKey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [decodeData length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [decodeData bytes], dataLength, buffer, bufferSize, &numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
NSData *data = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return result;
} else {
free(buffer);
return nil;
}
}
AES加密的细节还要和和后台商量。
二、非对称算法
算法公开,可逆的加密数据。一般服务器存私钥,客户端存公钥,且公钥是公开的。用公钥加密,就用私钥解密。用私钥加密,就用公钥解密。
特性:
速度慢,适合对小数据加密。
非对称算法比对称算法安全。
最常用的是RSA。
1、什么是RSA?
三个人一起发明了非对称算法,三个人名字的首字母分别是R、S、A,所以非对称算法加密就叫RSA加密。
2、RSA加密原理
1、找出两个‘很大’的质数:P & Q,一般长度是上百位。然后通过下面计算得到N和 M;
N = P * Q
M = (P - 1) * (Q - 1)
2、找出整数E,E与M互质,即除了1之外,没有其他公约数
3、找出整数D,使用ED除以M余1,即(ED) % M = 1
4、经过上述准备工作之后,可以得到:
E是公钥,负责加密
D是私钥,,负责解密
N负责公钥和私钥之间的联系
5、加密算法,假定对X进行加密
(X^E)%N = Y
6、解密算法,根据‘费马小定理',可以使用以下公式完成解密
(Y^D)%N = X
画外音:看懂的就看,看不懂的略过,反正我是看不懂~~
3、应用场景
由于 对称算法和非对称算法的特性,一般
1、用RSA算法加密并传输对称算法所需的密钥
2、数据本身的加密和解密使用对称加密算法(AES)
4、在iOS中的应用
1、需求:
SDK开发,使用RSA加密和后台进行数据交互,后台是PHP,公钥、私钥是后台高度,把公钥发给了我。
要求:
1、post请求,客户端放公钥,私钥放后台
2、先将上传的参数进行排序,再进行MD5加盐加密。
3、再将数据进行RSA加密。
4、使用的密钥是1024位,要和后台统一,解密长度128,加密长度117
5、rsa_public_key.pem文件后台给的
至于没有用对称算法传输数据,这个是后台决定的,每个公司的加密方法和顺序都不一样,具体问题具体分析。
4、遇到的问题
1、'openssl/asn1.h' file not found‘
解决方法:
Header Search Paths 添加这种格式的路径
"$(SRCROOT)/XSFH_game/Lib"
2、base编码发给后台,后台接收少+的问题
我这边发给后台加密后的base64编码,后台接收后,base64编码中的+变成了空格,导致后台解码错误,这是后台的问题
解决方法:
PHP学习 base64_encode +号变空格
3、后台数据接收到问题
可能是php接收数据的问题,我放在HTTPBody里的传给它的是一字符串,后台说没法解析,要那种类似于json的格式,最后给它传了个如下格式的代码stringWithFormat:@"baseKey=%@",encryptedString]; ,baseKey可以随便写,就类似于json的key值
NSString *encryptedString = [[XSFHRSATool shareInstance] encryptStr:paramStr WithRSAKeyType:KeyTypePublic];
NSString *keyAndValue = [NSString stringWithFormat:@"baseKey=%@",encryptedString];
request.HTTPBody = [keyAndValue dataUsingEncoding:NSUTF8StringEncoding];
三、散列算法
1、什么是散列算法
散列算法是不可逆的,MD5是其代表,又称作指纹算法,摘要算法。
- 特点:
1、对任意的数据,会生成固定长度的字符串。一般是32位。
2、相同数据的MD5值肯定一样,不同的数据会产生不同的字符串,但是重复的概率很小。
3、不可逆的,加密后的值一般解不出来,但是现在也可以通过暴力破解。 - 用途:
1、计算MD5的值,用户可以验证从网络上下载的文件是否在下载的过程中被修改了
2、一般用来加密密码
2、MD5在iOS的应用
#pragma mark - 3、散列加密
-(void)MD5Test{
NSString *str = @"我是中国人";
NSString *str1 = [self md5EncryptWithString:str];
NSLog(@"MD5加密=%@",str1);
}
//秘钥
static NSString *encryptionKey = @"nha735n197nxn(N′568GGS%d~~9naei';45vhhafdjkv]32rpks;lg,];:vjo(&**&^)";
- (NSString *)md5EncryptWithString:(NSString *)string{
return [self md5:[NSString stringWithFormat:@"%@%@", encryptionKey, string]];
}
- (NSString *)md5:(NSString *)string{
const char *cStr = [string UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, (CC_LONG)strlen(cStr), digest);
NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02X", digest[i]];
}
return result;
}
3、MD5更加安全的加密方式
- HMAC:
进行2次MD5加密。
A = 原密码+一个字符串 进行混合 进行MD5计算
B = A +原密码 再进行MD5计算
最后B就是MD5加密的结果。 - MD5 + 时间
1、A = (任意字符串进行MD5加密 + 用户密码)进行HMAC加密
2、从服务获取时间到分的字符串time
3、B = ( A + time)进行MD5加密
最后B就是MD5加密的结果。
怎么说呢,上面2种方式都是重复利用MD5加密
还可以更复杂,不过要和后台商量好就行了。
四、钥匙串
通过系统提供的钥匙串功能,可以在本地对用户的信息进行保存。系统使用AES方式对密码加密。
相对于NSUserDefaults、plist文件保存等一般方式,keychain保存更为安全。所以我们会用keyChain保存一些私密信息,比如密码、证书、设备唯一码(把获取到用户设备的唯一ID 存到keychain 里面这样卸载或重装之后还可以获取到id,保证了一个设备一个ID)等等。
一般使用第三方框架SSKeychain
#pragma mark - 4、SSKeychain
-(void)SSKeychainTest{
[SSKeychain setPassword:@"admin123" forService:[NSBundle mainBundle].bundleIdentifier account:@"张三"];
NSString *mima = [SSKeychain passwordForService:[NSBundle mainBundle].bundleIdentifier account:@"张三"];
NSLog(@"输出密码=%@",mima);
}
参考:
iOS AES加密
1、RSA加密、解密、签名、验签的原理及方法
2、一篇文章彻底弄懂Base64编码原理
3、iOS中使用基于RSA使用公钥加密和公钥解密
4、iOS RSA加签和验签(SHA1WithRSA)
5、iOS MD5加密