ios:NSUserDefaults如何安全存储数据

213 阅读3分钟

前言:ipa安全检测过程中发现,能检测到ipa中存储在沙盒里面的cookie信息,以及登录用户的敏感信息,这个就涉及到用户隐私安全问题了,针对以上问题我们采取了存储数据的加密的方法解决。

加密方法:字符串进行AES加密

NSData *EncipherData_AES(NSData *indata,CCOperation otype)
{
    NSData *retData = nil;
   //测试的密钥或向量
    Byte tkey[32] = {0};
    for (int i = 0; i < 32; i++) {
        tkey[i] = 8;
    }
    Byte iv[16] = {0};
    for (int i =0; i < 16; i++) {
        iv[i] = 1;
    }
    CCCryptorRef cryptor = NULL;

    CCCryptorStatus ccret;
    
  //创建加密解密器
    if (otype==kCCEncrypt) {
        ccret = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, tkey, kCCKeySizeAES256, iv, &cryptor);

    }
    else if (otype == kCCDecrypt)
    {
 
        ccret = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, tkey, kCCKeySizeAES256, iv, &cryptor);

    }
    if (ccret!=kCCSuccess) {
        return nil;
    }
    
    size_t bufsize = 0;
    size_t moved = 0;
    size_t total = 0;

  //获取最大长度
    bufsize = CCCryptorGetOutputLength(cryptor, indata.length, true);
    char * buf = (char*)malloc(bufsize);
    bzero(buf, bufsize);
    
  //加解密
    ccret = CCCryptorUpdate(cryptor,
                    indata.bytes,indata.length,
                    buf, bufsize, &moved);
    
    total += moved;
    if (ccret!=kCCSuccess) {
        return nil;
    }
    
  //处理最后的数据块
    ccret = CCCryptorFinal(cryptor,
                   buf+total,
                   bufsize-total, &moved);
    if (ccret!=kCCSuccess) {
        return nil;
    }
    total +=moved;
    CCCryptorRelease(cryptor);
    
  
    retData = [NSData dataWithBytes:buf length:total];
    free(buf);
    
    return retData;
}
NSData *EncipherData_AES(NSData *indata,CCOperation otype)
{
    NSData *retData = nil;
   //测试的密钥或向量
    Byte tkey[32] = {0};
    for (int i = 0; i < 32; i++) {
        tkey[i] = 8;
    }
    Byte iv[16] = {0};
    for (int i =0; i < 16; i++) {
        iv[i] = 1;
    }
    CCCryptorRef cryptor = NULL;

    CCCryptorStatus ccret;
    
  //创建加密解密器
    if (otype==kCCEncrypt) {
        ccret = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, tkey, kCCKeySizeAES256, iv, &cryptor);

    }
    else if (otype == kCCDecrypt)
    {
 
        ccret = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, tkey, kCCKeySizeAES256, iv, &cryptor);

    }
    if (ccret!=kCCSuccess) {
        return nil;
    }
    
    size_t bufsize = 0;
    size_t moved = 0;
    size_t total = 0;

  //获取最大长度
    bufsize = CCCryptorGetOutputLength(cryptor, indata.length, true);
    char * buf = (char*)malloc(bufsize);
    bzero(buf, bufsize);
    
  //加解密
    ccret = CCCryptorUpdate(cryptor,
                    indata.bytes,indata.length,
                    buf, bufsize, &moved);
    
    total += moved;
    if (ccret!=kCCSuccess) {
        return nil;
    }
    
  //处理最后的数据块
    ccret = CCCryptorFinal(cryptor,
                   buf+total,
                   bufsize-total, &moved);
    if (ccret!=kCCSuccess) {
        return nil;
    }
    total +=moved;
    CCCryptorRelease(cryptor);
    
  
    retData = [NSData dataWithBytes:buf length:total];
    free(buf);
    
    return retData;
}
NSData *aes_cbc_256(NSData *inData,NSData *key,CCOperation coType)
{
    NSData *retData = nil;
    if (!inData || !key) {
        return nil;
    }
    
    if (key.length!=32) {
        return nil;
    }

    
    NSUInteger dataLength = [inData length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus;
    
  //ecb 模式不需要使用 iv,cbc模式需要,当cbc模式时,如果不传iv,则默任全0
    Byte iv[16] = {0};
    for (int i = 0; i < 16; i++) {
        iv[i] = 1;
    }
    //加密
    if (coType==kCCEncrypt) {
        cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,//使用AES算法
                kCCOptionPKCS7Padding,
                key.bytes, kCCKeySizeAES256,
                iv,
                [inData bytes], dataLength,
                buffer, bufferSize,
                &numBytesEncrypted);
    }
    
    //解密
    else if(coType ==kCCDecrypt)
    {
        cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                kCCOptionPKCS7Padding,
                key.bytes, kCCKeySizeAES256,
                iv,
                [inData bytes], dataLength,
                buffer, bufferSize,
                &numBytesEncrypted);
    }
    
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    
    return retData;
}
#pragma mark - # 加密字符串
+ (NSData*)addEncipherDataWithString:(NSString*)string{
    
    NSData *srcData = [string dataUsingEncoding:NSASCIIStringEncoding];
    NSData *encData = EncipherData_AES(srcData, kCCEncrypt);
    return encData;
}
#pragma mark - # 解密
+ (NSString*)decryptEncipherDataWithData:(NSData*)encData{
    
    NSData *decData = EncipherData_AES(encData, kCCDecrypt);
    NSString *string = [[NSString alloc] initWithData:decData encoding:NSASCIIStringEncoding];
    return string;
}

这个代码里面2种加密方法,你可以选择AES加密,或者aes_cbc_256方案。

使用方法也很简单:

#define UD_(key) [[NSUserDefaults standardUserDefaults] objectForKey:key]
#define setUD_(key,value) [[NSUserDefaults standardUserDefaults] setObject:value forKey:key]

存储数据:

setUD_(USERNAME, [WSEncipherDataManager addEncipherDataWithString:@"test"]);

取数据:

NSString *userName = [WSEncipherDataManager decryptEncipherDataWithData:UD_(USERNAME)];

这样再去检测ipa的话,再看到的数据就是加密之后的二进制数据,保护了用户的隐私信息。