美文网首页
iOS 加密算法 AES加密与解密 加密中文失败问题

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

作者: 木子李55 | 来源:发表于2019-09-25 20:27 被阅读0次

    一、应用场景:数据存储到本地沙盒中,不重要的数据可以使用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再转为字符串就行了,这个在方法中已经补充上了。
    
    

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/mtkzectx.html