如何在OS-X应用程序中加密核心数据(sqllite)中的数据

use*_*624 3 encryption macos cocoa core-data

我发现如果我使用可转换类型的属性和NSXMLStoreType我的数据是加密的,那就是可转换类型的属性,是不可读的.不需要做任何其他事情,不需要代码.请注意,我正在使用使用核心数据的OS-X应用程序.

但是,如果我将我的商店类型更改为NSSQLiteStoreType,则情况并非如此.

我可以用sqllitebrowser打开数据库,选择可转换字段,如果我点击导出按钮,在生成的文本文件中,我可以正常读取值,即值(数据)未加密.

大约4个月前我问了同样的问题而我没有回答.

另外,我在stackoverflow上找到了这篇文章.

您可以通过创建可转换属性来加密Core Data模型实体中的各个属性,然后创建NSValueTransformer子类,该子类将加密和解密该属性的数据.

对我来说不幸的是,答案的作者@Brad Larson没有提供一个如何做到这一点的简单例子.

任何人都可以提供任何示例代码,说明如何加密可转换属性,以便它无法以任何方式读取?

ha1*_*100 6

你可以做一些像这里所示的跨平台AES加密

添加一个新的Objective-C文件到项目选择类别,NSData类称它为Additions

的NSData + Additions.h

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>

@interface NSData (Additions)

#pragma mark - data encryption

+ (NSData *)encrypt:(NSData *)plainText key:(NSData *)key iv:(NSData *)iv;
+ (NSData *)decrypt:(NSData *)encryptedText key:(NSData *)key iv:(NSData *)iv;

+ (NSData *)dataFromHexString:(NSString *)string;
+ (NSData *)sha256forData:(id)input;

+ (NSData *)generateRandomIV:(size_t)length;

@end
Run Code Online (Sandbox Code Playgroud)

的NSData + Additions.m

#import "NSData+Additions.h"

@implementation NSData (Additions)

+ (NSData *)encrypt:(NSData *)dataToEncrypt key:(NSData *)key iv:(NSData *)iv {

    NSUInteger dataLength = [dataToEncrypt length];

    size_t buffSize = dataLength + kCCBlockSizeAES128;
    void *buff = malloc(buffSize);

    size_t numBytesEncrypted = 0;

    CCCryptorStatus status = CCCrypt(kCCEncrypt,
                                     kCCAlgorithmAES128,
                                     kCCOptionPKCS7Padding,
                                     [key bytes], kCCKeySizeAES256,
                                     [iv bytes],
                                     [dataToEncrypt bytes], [dataToEncrypt length],
                                     buff, buffSize,
                                     &numBytesEncrypted);

    if (status == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buff length:numBytesEncrypted];
    }

    free(buff);
    return nil;
}

+ (NSData *)decrypt:(NSData *)encryptedData key:(NSData *)key iv:(NSData *)iv {

    NSUInteger dataLength = [encryptedData length];

    size_t buffSize = dataLength + kCCBlockSizeAES128;

    void *buff = malloc(buffSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus status = CCCrypt(kCCDecrypt,
                                     kCCAlgorithmAES128,
                                     kCCOptionPKCS7Padding,
                                     [key bytes], kCCKeySizeAES256,
                                     [iv bytes],
                                     [encryptedData bytes], [encryptedData length],
                                     buff, buffSize,
                                     &numBytesEncrypted);
    if (status == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buff length:numBytesEncrypted];
    }

    free(buff);
    return nil;
}

+ (NSData *)dataFromHexString:(NSString *)string {

    NSMutableData *stringData = [[NSMutableData alloc] init];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};

    for (int counter = 0; counter < [string length] / 2; counter++) {
        byte_chars[0] = [string characterAtIndex:counter * 2];
        byte_chars[1] = [string characterAtIndex:counter * 2 + 1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [stringData appendBytes:&whole_byte length:1];
    }

    return stringData;
}

+ (NSData *)sha256forData:(id)input {
    NSData *dataIn;

    if ([input isKindOfClass:[NSString class]]) {
        dataIn = [input dataUsingEncoding:NSUTF8StringEncoding];
    } else if ([input isKindOfClass:[NSData class]]) {

        NSUInteger dataLength = [input length];
        NSMutableString *string = [NSMutableString stringWithCapacity:dataLength * 2];
        const unsigned char *dataBytes = [input bytes];

        for (NSInteger idx = 0; idx < dataLength; ++idx)
            [string appendFormat:@"%02x", dataBytes[idx]];

        dataIn = [string dataUsingEncoding:NSUTF8StringEncoding];
    }

    NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];

    CC_SHA256(dataIn.bytes, (CC_LONG)[dataIn length],  [macOut mutableBytes]);

    return macOut;
}

+ (NSData *)generateRandomIV:(size_t)length {
    NSMutableData *data = [NSMutableData dataWithLength:length];

    SecRandomCopyBytes(kSecRandomDefault, length, [data mutableBytes]);

    return data;
}

@end
Run Code Online (Sandbox Code Playgroud)

那么你将需要用户名,密码,iVector和一些随机盐.在盐我已经使用替换#随机字符,但要确保如果你使用%不要忘记加倍它%%否则它将是不完整的格式说明符警告.

在你的班级中使用它

#define CC_USERNAME         @"secretName"
#define CC_PASSWORD         @"secretPassword"
#define CC_SALTED_STRING    [NSString stringWithFormat:@"####################%@#####################", CC_PASSWORD]
Run Code Online (Sandbox Code Playgroud)

然后创建通过SHA256运行的盐渍字符串的NSData表示

NSData *hash = [NSData sha256forData:CC_SALTED_STRING];
Run Code Online (Sandbox Code Playgroud)

下一步是生成16字节的随机生成的iVector数据

NSData *iVector = [NSData generateRandomIV:16];
Run Code Online (Sandbox Code Playgroud)

并使用这些对象加密您的字符串.使用前16个字节的iVector数据创建一个NSMutableData对象(确保使用iVector对象并且不生成新的随机数,否则您将无法解密).

NSString *message = @"my secret message to the world";
NSData *messageData = [message dataUsingEncoding:NSUTF8StringEncoding];

NSMutableData *encryptedData = [[NSMutableData alloc] initWithData:iVector];

NSData *payLoad = [NSData encrypt:messageData key:hash iv:iVector];

[encryptedData appendData:payLoad];
Run Code Online (Sandbox Code Playgroud)

解密,分离前16个字节和其余数据,并将其与哈希一起使用.

NSData *pureData = [encryptedData subdataWithRange:NSMakeRange(16, [encryptedData length] - 16)];
NSData *extractedVector = [encryptedData subdataWithRange:NSMakeRange(0, 16)];

NSData *decryptedData = [NSData decrypt:pureData key:hash iv:extractedVector];

NSString *decryptedMessage = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
Run Code Online (Sandbox Code Playgroud)

您可以在哈希上做一些额外的md5,甚至在存储之前用zlib打包加密数据.

享受你定制的加密.