一、应用场景:数据存储到本地沙盒中,不重要的数据可以使用NSUserDefaults、wirteToFile等方式存储到本地;如果重要数据为了安全,需要对数据加密后存储,使用的时候再拿出来解密。
二、常用加密算法:
1.对称加密算法中的带头大哥:AES;
2.非对称加密算法中的带头大哥:RSA;
3.阿里的mpaas移动开发平台,本地存储使用的默认加密算法就是AES;
三、所以就研究了下AES的加密与解密:
(AES全称Advanced Encryption Standard,中文名称叫高级加密标准,在密码学中被叫做Rijndael加密法,这个标准已经替代原来的DES,成为美国政府采用的一种区块加密标准。微信小程序中的加密传输就是使用的AES加密算法。)
原理思路:
// 明文 + 密钥 --通过加密函数得到-- 密文
// --网络传输--
// 密文 + 秘钥 --通过解密函数得到-- 明文
// 在对称加密中,加密和解密的密钥是相同的,所以密钥要保证安全,如果一旦密钥泄漏了,那么数据就基本上不存在安全性了。
代码:
可以把加密与解密的方法放到一个工具类里
.h中
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface LYTool : NSObject
//** AES对NSData加密
+(NSData *)encryptNSData:(NSData *)data;
//** AES对NSData解密
+(NSData *)decryptNSData:(NSData *)data;
//** AES对NSSting加密
+(NSString *)encryptNSSting:(NSString *)string;
//** AES对NSSting解密
+(NSString *)decryptNSSting:(NSString *)string;
//** 字符串转为base64
+(NSString *)base64WithStr:(NSString *)str;
//** base64转为字符串
+(NSString *)strWithBase64:(NSString *)base64;
@end
.m中
//** 加密算法
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#define AESKey @"123456789" // AES对称加密,加密用秘钥与解密用秘钥相同
@implementation LYTool
//** AES对NSData加密
+(NSData *)encryptNSData:(NSData *)data{
char keyPtr[kCCKeySizeAES256 + 1];
bzero(keyPtr, sizeof(keyPtr));
[AESKey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, NULL, [data bytes], dataLength, buffer, bufferSize, &numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
//** AES对NSData解密
+(NSData *)decryptNSData:(NSData *)data{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[AESKey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeAES128,
NULL,
[data bytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
//** AES对NSSting加密
+(NSString *)encryptNSSting:(NSString *)string{
// 先把字符串转化为base64
NSString *base64Str = [self base64WithStr:string];
const char *cstr = [base64Str cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:base64Str.length];
//对数据进行加密
NSData *result = [self encryptNSData:data];
//转换为2进制字符串
if (result && result.length > 0) {
Byte *datas = (Byte*)[result bytes];
NSMutableString *output = [NSMutableString stringWithCapacity:result.length * 2];
for(int i = 0; i < result.length; i++){
[output appendFormat:@"%02x", datas[i]];
}
return output;
}
return nil;
}
//** AES对NSSting解密
+(NSString *)decryptNSSting:(NSString *)string{
//转换为2进制Data
NSMutableData *data = [NSMutableData dataWithCapacity:string.length / 2];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [string length] / 2; i++) {
byte_chars[0] = [string characterAtIndex:i*2];
byte_chars[1] = [string characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
//对数据进行解密
NSData* result = [self decryptNSData:data];
if (result && result.length > 0) {
// 把base再转化为字符串
NSString *base64Str = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
return [self strWithBase64:base64Str];
}
return nil;
}
+(NSString *)base64WithStr:(NSString *)str{
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];return [data base64EncodedStringWithOptions:0];
}
+(NSString *)strWithBase64:(NSString *)base64{
NSData *nsdataFromBase64String = [[NSData alloc]initWithBase64EncodedString:base64 options:0];NSString *base64Decoded = [[NSString alloc]initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding];return base64Decoded;
}
@end
// 使用:
// 对NSData加密 (文字或图片或其他文件数据可以加密存储到本地)
// NSData *testData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"shutu9" ofType:@"jpeg"]];
// NSData *enData = [LYTool encryptNSData:testData];
// NSLog(@"密文:%@", enData); // <7a9b168a c0dcca5c 5f85a29d 6d882eb3 1e37a9ff f0e62c56 726920ae 4ced1819>
// 对NSData解密
// NSData *deData = [LYTool decryptNSData:enData];
// NSLog(@"明文:%@", deData);
// UIImageView *testImgView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 100, 200, 200)];
// testImgView.backgroundColor = [UIColor grayColor];
// testImgView.image = [UIImage imageWithData:deData];
// [self.view addSubview:testImgView];
// 对NSString加密 直接对中文加密解密会失败,需要转化为base64进行加解密
// NSString *enStr = [LYTool encryptNSSting:@"卧槽"];
// NSLog(@"密文:%@", enStr);
// 对NSString解密
// NSString *deStr = [LYTool decryptNSSting:enStr];
// NSLog(@"明文:%@", deStr);
// 小结:使用时在自己的工具类里把方法的声明和实现拷进去就行;耗时最长的一点就是参考别人的方法时,加密英文是可以加密解密的,但是加密中文时解密出来总是null,后来加密时先把字符串转为base64再加密,解密时把解出来的base64再转为字符串就行了,这个在方法中已经补充上了。
网友评论