iOS 加密算法 AES加密与解密 加密中文失败问题

一、应用场景:数据存储到本地沙盒中,不重要的数据可以使用NSUserDefaults、wirteToFile等方式存储到本地;如果重要数据为了安全,需要对数据加密后存储,使用的时候再拿出来解密。

二、常用加密算法:
1.对称加密算法中的带头大哥:AES;
2.非对称加密算法中的带头大哥:RSA;
3.阿里的mpaas移动开发平台,本地存储使用的默认加密算法就是AES;

三、所以就研究了下AES的加密与解密:

(AES全称Advanced Encryption Standard,中文名称叫高级加密标准,在密码学中被叫做Rijndael加密法,这个标准已经替代原来的DES,成为美国政府采用的一种区块加密标准。微信小程序中的加密传输就是使用的AES加密算法。)

原理思路:

    // 明文 + 密钥 --通过加密函数得到-- 密文
    // --网络传输--
    // 密文 + 秘钥 --通过解密函数得到-- 明文
   // 在对称加密中,加密和解密的密钥是相同的,所以密钥要保证安全,如果一旦密钥泄漏了,那么数据就基本上不存在安全性了。

代码:

可以把加密与解密的方法放到一个工具类里
.h中
#import 
#import 
@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 
#import 
#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再转为字符串就行了,这个在方法中已经补充上了。

你可能感兴趣的:(iOS 加密算法 AES加密与解密 加密中文失败问题)