【问题标题】:Core data functionality without using coredata不使用 coredata 的核心数据功能
【发布时间】:2012-10-05 15:22:33
【问题描述】:

我正在维护一个 iOS 应用程序,该应用程序当前使用 Core Data 从数据库中获取数据并填充表视图。提出了一个新要求,即必须使用 SQLCypher 对整个数据库进行加密,根据我的研究,Core Data 拒绝使用密码。因此,决定删除 coredata 支持,现在必须手动进行数据库调用。在这种情况下,是否有任何库/项目可以模拟 CoreData 中 NSFetchedResults 的功能来管理数据库交互并与 TableViews 配合得很好?

我正在寻找有关构建项目的建议,以使使用 sql 语句的代码数量最少以进行数据库交互。任何人都可以就如何实现这一点提出建议吗?

谢谢

【问题讨论】:

  • 他们想要将整个数据库加密为一个文件还是仅加密数据库中的条目?因为我曾经不得不加密 Core Data 数据库中的部分条目,而且很容易完成......
  • 我相信整个数据库。显然是来自上级的严格要求
  • mmh 好吧,我还是发布了我的解决方案,也许“高层”在看到集成 SQLCypher 所需的工作量时会改变他们的决定......
  • @benjamin83 - 加密单个条目非常不安全,并且不符合许多严格的安全标准。
  • 我们有一些医疗应用程序,为了满足 HIPAA 标准,我们发现我们必须使用 SQLCiper(或类似的东西)并在顶部“滚动我们自己的”层。 (因为我们在 Core Data 之前就一直在这样做,所以我们还没有对 Core Data 的任何支持层进行建模。)

标签: objective-c ios sqlite core-data


【解决方案1】:

也许这个解决方案可以帮助您保留核心数据并为内容提供加密。

假设我们有一个名为 MyObject 的 Core Data 对象,它具有一个属性 MyData。然后在 CoreData 模型中为该属性设置属性 transient。现在定义第二个属性 MySecretData,属性类型为 Binary Data。这是存储实际数据的地方。

现在在 NSManagedObject 子类上创建一个类别,如下所示:

@interface MyObject (Access)

- (NSData*)myData;
- (void)setMyData:(NSData*)value;

@end

@implementation MyObject (Access)

- (NSData*)MyData {
    NSMutableData * tmpValue;

    [self willAccessValueForKey:@"MyData"];
    tmpValue = [self primitiveValueForKey:@"MyData"];
    [self didAccessValueForKey:@"MyData"];

    if(!tmpValue) {
        NSData *encryptedData = [self valueForKey:@"MySecretData"];
        if(encryptedData) {            
            tmpValue = [NSMutableData dataWithData:encryptedData];
            BOOL success = [tmpValue decryptWithKey:nil];
            if (!success) {
                // Error Handling here
            }
            tmpValue = [tmpValue zlibInflate];
            [self setPrimitiveValue:tmpValue forKey:@"MyData"];
        }
        else {
            tmpValue = nil;
            [self setMyData:tmpValue];
        }
    }
    return tmpValue;
}

- (void)setMyData:(NSData *)data {
    NSData* tmpValue;
        [self willAccessValueForKey:@"MyData"];
        tmpValue = [self primitiveValueForKey:@"MyData"];
        [self didAccessValueForKey:@"MyData"];

        if([tmpValue isEqual:data])
        return;

        [self willChangeValueForKey:@"MyData"];
        [self setPrimitiveValue:data forKey:@"MyData"];
        [self didChangeValueForKey:@"MyData"];
        NSMutableData* encryptedData = nil;
        if (data != nil) {
            encryptedData = [NSMutableData dataWithData:data];
            encryptedData = [encryptedData zlibDeflate];
            BOOL success = [encryptedData encryptWithKey:nil];
            if (!success) {
                // Error Handling here
            }

        }
        [self setPrimitiveValue:encryptedData forKey:@"MySecretData"];
}

@end

在这种情况下,数据被加密并被压缩。从您的代码中,您可以照常访问 MyData。在核心数据库中,所有值都将被加密。当然,你必须使用适当的加密函数。

【讨论】:

  • 请记住,使用此方案时,您的任何关键字段都无法加密。而且它不是特别安全。
  • @Hot Licks:就我而言,如果有人复制数据库文件并使用另一个应用程序打开它,则必须保护某些字段。你能解释一下为什么这不是特别安全吗?我真的很感兴趣,因为它正在应用中使用。
  • 使用相同密钥反复重新加密的短序列很容易受到“已知明文”攻击。基本上,在许多情况下,无聊的大学黑客可能会破解代码。像 SQLCipher 这样的东西一次加密整个数据“页面”,并使用“盐”值进行加密,因此已知的明文攻击基本上是不可能的。
【解决方案2】:

我认为没有一个好的、简单的答案。一些可能性:

  • iOS 可以自动加密其文件系统。这对 Core Data 来说是透明的,你只需要在访问任何文件之前确保它是“解锁的”。显然这不会使用 SQLCypher(不管是什么)
  • 我不确定 SQLCypher 是如何工作的,但您可以编写自己的 NSPersistentStore 来与加密数据库通信。同样,这对 Core Data 来说是透明的,尽管这可能是不可能的。这完全取决于 SQLCypher 的工作方式
  • 编写您自己的类似 Core Data 的层。据我所知,没有什么比得上它了……我的意思是,当 Apple 总是可用的时候,你为什么要自己编写(如果你有任何高于 iOS3 的东西的话)

无论你怎么看,工作量都很大。

【讨论】:

  • 该应用目前未使用任何有用的核心数据功能(缓存/预取),因此它实际上只是需要模拟的核心功能。
  • SQLCipher 保持整个数据库加密(每个扇区单独),而不是在主动使用数据库时解密为临时副本,或加密/解密单个字段。后两种方案都存在严重的安全隐患。
  • @HotLicks 不确定 Apple 的解决方案是如何工作的,但其他两个选项都不需要您解密为临时副本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
  • 1970-01-01
相关资源
最近更新 更多