在iPhone OS中加密SQLite数据库文件

时间:2009-05-30 13:39:02

标签: iphone sqlite ios encryption checksum

iPhone上的任何SQLite数据库都只是与应用程序捆绑在一起的文件。任何人都可以相对简单地提取此文件并进行查询。

您对加密数据库中存储的文件或数据有何建议。

编辑:该应用是一款将与其他用户对战的游戏。有关用户相对优势和劣势的信息将存储在DB中。我不希望用户能够在手机上破坏他们的声誉/权力等,然后赢得锦标赛/联赛等(注意:因为这个想法属于NDA而试图变得含糊不清)。

我不需要军事加密,我只是不想用纯文本存储东西。

编辑2:稍微澄清一点,我的主要目标是

  1. 使攻击敏感数据变得非常重要
  2. 有一种简单的方法可以发现数据是否已被更改(某种校验和)

8 个答案:

答案 0 :(得分:18)

您无法信任客户,期间。如果您的独立应用程序可以解密它,那么它们也将解密。要么将数据放在服务器上,要么不要打扰,因为实际破解它以增强统计数据的人数将是微不足道的,并且他们应该因为努力而获得奖励!

在数据库中输入一个字符串,上面写着“请不要作弊”。

答案 1 :(得分:12)

这里至少有两种更简单的方法(两种都是免费的)可以避免加密值或内存数据库:

#1 - ipa裂缝检测

避免加密数据库和/或内容的技术(和法律)麻烦,只是确定应用程序是否是盗版并禁用游戏的网络/评分/排名方面。有关详细信息,请参阅以下内容:

http://thwart-ipa-cracks.blogspot.com/2008/11/detection.html

#2 - 数据完整性验证

或者在保存数据时(以及在初始sqlite数据库中)存储每行中重要列的HMAC / salted哈希值。加载每一行时,根据HMAC / hash验证数据,如果验证失败则相应地采取行动。

这两种方法都不会强迫您填写Apple / US政府要求的加密导出表单。

分数提交

不要忘记您需要为实际分数提交做类似的事情,以防止来自您的应用以外的其他内容的值。你可以在http://code.google.com/p/cocos2d-iphone/http://code.google.com/p/cocoslive/

的cocos2d-iphone和cocoslive框架中看到这个的实现。

对评论的回应

此处没有解决方案可以100%防止数据被篡改。如果这是一项要求,则客户端只需要查看,并且必须在受信任的服务器上计算所有状态和逻辑。根据应用程序,客户端将需要额外的反作弊机制。

有许多关于开发大型多人游戏的书籍,讨论这些问题。

在代码中使用已知秘密的哈希可能是一种合理的方法(至少在考虑App Store中通常存在的应用程序类型时)。

答案 2 :(得分:11)

像肯德尔所说,包括设备上的密钥基本上是要求破解。但是,有些人有理由使用设备上的密钥来混淆数据。如果您决定这样做,可以考虑使用SQLCipher进行实施。它是SQLite的一个版本,它为整个数据库提供透明的页面级加密。在iPhone应用程序中使用它有一个tutorial over on Mobile Orchard

答案 3 :(得分:5)

您认为普通用户会这样做的可能性有多大?我假设您正在浏览应用程序商店,这意味着在进入用户设备之前,所有内容都已签名/加密。他们必须越狱他们的设备才能访问您的数据库。

您存储的是哪种数据需要加密?如果它包含用户输入的密码,那么您实际上并不需要加密它们;用户无需查找自己的密码。如果它只是您希望用户通过应用程序访问的通用BLOB数据,则可以像使用security API存储加密blob一样简单。

如果它是您希望保护的整个数据库,那么您仍然希望使用安全api,而是在整个文件上,并在打开之前根据需要解密文件。这里的问题是,如果应用程序在没有清理的情况下关闭,则会留下一个解密文件。

您可能需要查看内存驻留数据库或临时数据库,您可以使用模板db或程序中的硬编码模式创建这些数据库(请参阅sqlite3_open的文档)。可以解密数据,将其插入临时数据库,然后删除解密的数据库。关闭连接时,请按相反方向进行。

修改

您可以制作自己的加密方案我只需要一个非常简单的安全系统,通过使用存储在应用程序中的值对数据进行异或,并在其他地方存储哈希以确保它不会更改或者别的什么。

答案 4 :(得分:3)

<强> SQLCipher:

根据我的经验,SQLCipher是加密数据库的最佳选择。

设置密钥(“PRAGMA密钥”)​​后,SQLCipher将自动加密数据库中的所有数据!请注意,如果您未设置密钥,则SQLCipher将与标准SQLite数据库完全相同。

对sqlite3_key或“PRAGMA key”的调用应该在打开数据库后作为第一个操作发生。在大多数情况下,SQLCipher使用PBKDF2(一个盐渍和迭代密钥派生函数)来获取加密密钥。或者,应用程序可以告诉SQLCipher以blob表示法使用特定的二进制密钥(请注意,SQLCipher只需要256位密钥材料),即

enter image description here

参考:

http://sqlcipher.net/ios-tutorial

我希望有人能节省时间探索这个

答案 5 :(得分:2)

忽略哲学和出口问题,我建议你最好直接加密表格中的数据。

您需要对代码中的解密密钥进行模糊处理。通常,这意味着将它们分成几部分并以十六进制编码字符串并使用函数将键的各个部分组合在一起。

对于算法,我会使用AES的可信实现来处理您正在使用的任何语言。 也许这个用于C#:

http://msdn.microsoft.com/en-us/magazine/cc164055.aspx

最后,您需要了解该方法的局限性。即,解密密钥是弱链接,它将在运行时以明文形式在内存中可用。 (至少)必须这样才能使用它。加密方案的实施是另一个弱点 - 任何缺陷都存在代码中的缺陷。正如其他几位人士所指出的,您的客户端 - 服务器通信也是可疑的。

您应该记住,您的可执行文件可以在十六进制编辑器中进行检查,其中明文字符串将从您编译的代码的随机垃圾中跳出。并且可以反向编译许多语言(例如C#),并且所有缺少的语言都是注释。

所有这一切,加密你的数据将提高作弊的标准。多少取决于你多么小心;但即便如此,坚定的对手仍将破坏你的加密和欺骗。此外,他们可能会编写一个工具,以便在您的游戏受欢迎时轻松实现;那时候你会有一场军备竞赛。


关于校验和值,您可以根据行中值的总和计算校验和,假设您在数据库中有足够的数值来执行此操作。或者,对于一堆布尔值,您可以将它们存储在varbinary字段中,并使用按位独占运算符^来比较它们 - 您最终应该为0。

例如,

表示数字列,

2 | 3 | 5 | 7 |校验和列| 17 |

对于布尔人来说,

0 | 1 | 0 | 1 |校验和列| 0101 |

如果这样做,您甚至可以在总结校验和的末尾添加摘要行。虽然如果您不断添加新记录,这可能会有问题。您还可以将字符串转换为ANSI / UNICODE组件并对它们求和。

然后,当您想要检查校验和时,请执行以下选择:

Select * 
FROM OrigTable 
right outer join 
(select pk, (col1 + col2 + col3) as OnTheFlyChecksum, PreComputedChecksum from OrigTable) OT on OrigTable.pk = OT.pk
where OT.OnTheFlyChecksum = OT.PreComputedChecksum

答案 6 :(得分:1)

将所有锦标赛结果同步到锦标赛中的所有iPhone似乎最简单。你可以在每场比赛中都这样做:在比赛之前,如果两部手机的数据库相互矛盾,就会显示警告。

如果用户A在与用户B的游戏中伪造结果,则该结果将传播直到B最终看到它,并警告A的数据与他的手机不匹配。然后,他可以去向A解释他的行为是不对的,就像现实生活中某人作弊一样。

当您计算最终比赛结果时,显示警告,名称名称,并抛弃所有结果相互矛盾的游戏。这消除了欺骗的动机。

如前所述,加密无法解决问题,因为您无法信任客户端。即使你的普通人不能使用反汇编程序,所需要的只是一个有动力的人,你所拥有的任何加密都将被破坏。

答案 7 :(得分:-5)

然而,如果在Windows平台上,您也可以选择SQLiteEncrypt来满足您的需求.SQLiteEncrypt扩展了sqlite加密支持,但您可以将其视为原始的sqlite3 c库。