在iPhone OS中encryptionSQLite数据库文件

iPhone上的任何SQLite数据库都只是一个与应用程序捆绑在一起的文件。 任何人提取这个文件并查询它都是相对简单的。

你有什么build议encryption文件或存储在数据库中的数据。

编辑:该应用程序是一个游戏,将对其他用户玩。 有关用户相对优势和弱点的信息将存储在数据库中。 我不希望用户能够将手机的声誉/权力等问题囚禁起来,然后赢得比赛/联赛等(注意:由于这个想法是在NDA之下,所以要模糊)。

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

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

  1. 使敏感数据变得不重要
  2. 有一个简单的方法来发现数据是否被改变(某种校验和)

你不能相信客户,期限。 如果您的独立应用程序可以解密,他们也可以解密。 要么把数据放在服务器上,要么不要打扰,因为实际上破解它来增强统计数据的人数是微不足道的,而且他们也许应该为此付出代价!

把一个string放在数据库中,说“请不要作弊”。

至less有两个方法可以避免encryption值或内存数据库:

#1 – IPS裂纹检测

避免encryption数据库和/或内容的技术(和法律)麻烦,只是确定应用程序是否被盗版,并禁用游戏的networking/评分/排名方面。 有关更多详情,请参阅以下内容

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

#2 – 数据完整性validation

或者在保存数据时(以及在你最初的sqlite数据库中),在每一行中存储重要列的HMAC / salted哈希值。 当加载每一行时,validation数据对HMAC /哈希,如果validation失败相应的行为。

这两种方法都不会迫使你填写苹果/美国政府要求的encryption出口表格。

分数提交

不要忘记,你需要做一些类似的实际评分提交,以防止价值来自除你的应用程序以外的东西。 您可以在http://code.google.com/p/cocos2d-iphone/和http://code.google.com/p/cocoslive/上的cocos2d-iphone和cocoslive框架中看到这个实现。

回应评论

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

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

在代码中使用已知秘密的散列可能是一个合理的方法(至less在考虑App Store中通常存在的应用程序的types时)。

就像肯德尔说的,包括设备上的关键基本上是要求破解。 然而,有些人有他们的理由用设备上的密钥来模糊数据。 如果你决定这样做,你可以考虑使用SQLCipher来实现。 这是一个SQLite的构build,提供了整个数据库的透明,页面级encryption。 Mobile Orchard上有一个关于在iPhone应用程序中使用它的教程 。

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

你要存储什么types的数据,以便它需要encryption? 如果它包含用户input的密码,那么你并不需要encryption它们。 用户将不需要找出自己的密码。 如果只是希望用户通过应用程序访问的通用BLOB数据,则可以像使用安全API存储encryption的blob一样简单。

如果它是你想保护的整个数据库,那么你仍然希望使用安全API,而是在整个文件上,并在打开之前根据需要解密文件。 这里的问题是,如果应用程序closures而没有清理,则只剩下一个解密文件。

您可能需要查看驻留在内存中的数据库或临时数据库,您可以使用模板db或程序中的硬编码模式(请参阅sqlite3_open的文档)创build临时数据库。 数据可以被解密,插入临时数据库,然后删除解密的数据库。 closures连接时,朝相反的方向进行操作。

编辑

你可以用你自己的encryptionscheme来制作一个非常简单的安全系统,通过将数据与存储在应用中的值进行异或,并在其他地方存储一个散列以确保它不会改变,或者。

SQLCipher:

根据我的经验,SQLCipher是encryption数据库的最佳select。

一旦设置了密钥(“PRAGMA密钥”)​​,SQLCipher将自动encryption数据库中的所有数据! 请注意,如果您未设置密钥,则SQLCipher将与标准SQLite数据库的操作相同。

打开数据库之后,应该首先调用sqlite3_key或“PRAGMA key”作为第一个操作。 在大多数情况下,SQLCipher使用PBKDF2(一种腌制和重复的密钥导出函数)来获取encryption密钥。 或者,应用程序可以告诉SQLCipher在blob表示法中使用特定的二进制密钥(请注意,SQLCipher只需要256位的密钥材料),即

在这里输入图像说明

参考:

http://sqlcipher.net/ios-tutorial 

我希望有人能省下时间来探讨这个问题

忽略哲学和出口问题,我build议你最好直接encryption表中的数据。

您需要在代码中混淆解密密钥。 通常,这意味着将它们拆分成小块并以hex编码string,并使用函数将这些键组合在一起。

对于algorithm,我会使用任何你使用的语言的AES的可信实现。 也许这一个为C#:

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

最后,你需要意识到这种方法的局限性。 也就是说,解密密钥是一个薄弱环节,它将在运行时以明文方式在内存中可用。 (至less)它必须这样才能使用它。 你的encryptionscheme的实现是另一个弱点 – 你的代码也有缺陷。 正如其他几位人士指出的那样,您的客户机 – 服务器通信也是可疑的。

您应该记住,您的可执行文件可以在hex编辑器中进行检查,其中明文string将跳出随机垃圾,即已编译的代码。 而且很多语言(比如C#)可以被反编译,而所有缺less的就是注释。

所有这一切,encryption你的数据将提高作弊的一点吧。 多less取决于你多么小心; 但即使如此,一个坚定的对手仍然会打破你的encryption和作弊。 而且,如果你的游戏很受欢迎,他们可能会写一个工具让它变得容易。 在这一点上,让你有一个怀旧的场景。


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

例如,

对于数字列,

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

对于布尔人来说,

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

如果你这样做,你甚至可以添加一个汇总行,总结你的校验和。 尽pipe如果您不断添加新logging,这可能会有问题。 您也可以将string转换为它们的ANSI / UNICODE组件并对其进行求和。

然后当你想检查校验和简单做一个select像这样:

 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 

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

如果用户A伪造了与用户B的比赛结果,则该结果将传播,直到B最终看到它,并且警告A的数据与他的电话不匹配。 然后,他可以去向A解释他的行为是不正确的,就像现实生活中有人作弊一样。

当你计算最后的锦标赛结果时,显示警告,名字的名字,并抛出所有有矛盾结果的游戏。 这消除了欺骗的动机。

如前所述,encryption不会解决问题,因为您不能信任客户端。 即使你的普通人不能使用反汇编,所需要的只是一个有动机的人,而且你所拥有的任何encryption都将被打破。

但是,如果在Windows平台上,您也可以selectSQLiteEncrypt来满足您的需求.SQLiteEncrypt扩展了sqliteencryption支持,但您可以将其视为原始的sqlite3 c库。