20

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

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

编辑:该应用程序是一款将与其他用户对战的游戏。有关用户相对优势和劣势的信息将存储在数据库中。我不希望用户能够越狱手机以提高他们的声誉/权力等,然后赢得锦标赛/联赛等(注意:由于这个想法处于 NDA 之下,所以试图含糊其辞)。

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

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

  1. 让破解敏感数据变得轻而易举
  2. 有一种简单的方法来发现数据是否已被更改(某种校验和)
4

8 回答 8

19

你不能相信客户,期间。如果您的独立应用程序可以解密它,那么它们也可以。要么将数据放在服务器上,要么不要打扰,因为真正破解它以增强统计数据的人数将是微不足道的,无论如何他们可能应该因为努力而得到回报!

在数据库中放入一个字符串,说“请不要作弊”。

于 2009-06-02T22:13:44.807 回答
12

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

#1 - ipa 裂纹检测

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

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

#2 - 数据完整性验证

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

这两种方法都不会强制您填写 Apple/美国政府要求的加密导出表格。

分数提交

不要忘记,您需要为实际提交的分数执行类似的操作,以防止值来自您的应用程序以外的其他内容。您可以在http://code.google.com/p/cocos2d-iphone/http://code.google.com/p/cocoslive/的 cocos2d-iphone 和 cocoslive 框架中看到这个实现

对评论的回应

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

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

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

于 2009-06-02T05:34:52.073 回答
11

就像 Kendall 说的,包括设备上的密钥,基本上就是要求被破解。但是,有些人有理由使用设备上的密钥来混淆数据。如果您决心这样做,您可以考虑使用SQLCipher来实现。它是 SQLite 的构建,可提供整个数据库的透明、页面级加密。有一个关于 Mobile Orchard 的教程,用于在 iPhone 应用程序中使用它。

于 2009-06-29T14:21:52.783 回答
5

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

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

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

您可能想查看内存驻留数据库或临时数据库,您可以使用模板数据库或程序中的硬编码模式创建它们(查看sqlite3_open的文档)。数据可以被解密,插入临时数据库,然后删除解密的数据库。关闭连接时以相反的方向执行此操作。

编辑

您可以使用存储在应用程序中的值对数据进行异或运算,并在其他地方存储哈希以确保它不会更改或其他东西,我敢肯定,您可以使用一个非常简单的安全系统来制作自己的加密方案.

于 2009-05-30T15:08:59.730 回答
3

SQL密码:

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

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

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

在此处输入图像描述

参考:

http://sqlcipher.net/ios-tutorial

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

于 2014-06-13T08:49:06.990 回答
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
于 2009-06-04T15:08:10.547 回答
1

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

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

当您计算最终的锦标赛结果时,显示警告、命名并丢弃所有结果相互矛盾的游戏。这消除了作弊的动机。

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

于 2009-06-08T13:27:19.947 回答
-5

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

于 2010-01-07T13:16:23.223 回答