在(开放)源代码中保守字符串秘密


50

我已经完成了针对Android的应用开发,并打算使用GPL进行发布-我希望它是开源的。但是,应用程序(游戏)的性质是,它会询问谜语并将答案编码到字符串资源中。我无法发布答案!有人告诉我要安全地存储密码-但是我没有找到合适的密码。

是否可以使用隐藏,加密或其他方式隐藏的字符串数组来发布我的源代码?也许通过阅读在线数据库的答案?

更新资料

Yuval Filmus的以下解决方案有效。当我第一次阅读它时,我仍然不确定该怎么做。对于第二个选项,我找到了一些解决方案:将散列的解决方案存储在源中,并在用户每次猜测时计算散列。为此,请使用http://code.google.com/p/crypto-js/上的crypto-js库。对于Android,请使用MessageDigest函数。在fdroid / github上有一个名为HashPass的应用程序可以执行此操作。


11
我不知道这里的主题如何;无论如何,它可能更适合于信息安全
拉斐尔

2
@YuvalFilmus不要被“热门问题”的投票所欺骗。但是要点。
拉斐尔

4
这里缺少的重要细节是:您是否只想验证用户答案还是要能够打印正确答案?并且,您是否需要任何模糊的表述,还是仅存在一组有限的正确答案(以便您可以按照此答案一一检查用户答案)?
海德2014年

4
所有答案都在询问您要解决的问题。您为什么不能发布答案?
Rhymoid 2014年

1
您的代码需要如何处理这些字符串?是否需要能够解码它们?还是能够将字符串与它们进行比较?
David Schwartz 2014年

Answers:


83

根据您要解决的问题,您至少有两个选择。

如果您希望代码的无辜读者不要无意间得到答案,或者至少要使其变得有点困难以使用户不受诱惑,则可以对解决方案进行加密并将密钥存储为代码的一部分,也许一些计算的结果(使其更加困难)。

如果要阻止用户检索答案,可以使用单向功能,也可以在计算机术语中使用哈希功能。存储答案的哈希,他们可以测试答案是否没有它可能推断出正确的答案在所有不先找到它。这样做的缺点是,即使对于这个问题也有一些解决方案,但很难检查出接近正确答案的答案。


9
我要补充的一件事是,如果您需要更高的安全性,则每个答案可能都应加上不同的盐。这样可以避免一次字典攻击所有答案。如果您想了解“真正的”加密人员的工作方式,请查看OpenPGP的String-to-Key系统
别名2014年

1
在代码中保留哈希值意味着所有信息都是静态的,盐/其他信息也将随时可用。我认为,如果答案空间足够大(例如32位整数值的整个范围),那将是合理的,否则(例如,在多项选择题的情况下)彩虹表将迅速给出正确答案。
Alexei Levenkov 2014年

3
正如Alexei所指出的那样,如果您可能的输入范围很小,那么将答案存储在代码中将向任何确定的攻击者开放-我猜大多数谜语的状态空间都非常小,因为它们的答案通常必须是单词或相对较小的数字。您可以哈希或加密以避免无辜的错误,但是并不能阻止某人获得真正想要的答案。(另外,他们可以问已经解决了您的谜语的人!)
克里斯·海斯

4
为了反驳克里斯所说的,您可以选择一个非常慢的哈希过程,比如说它需要100毫秒(这是某些PK标准所采用的方法)。从用户的角度来看,这仍然非常快,但是使枚举变得更加困难。
Yuval Filmus 2014年

12
@YuvalFilmus再次,在一定程度上。如果您的谜语结尾是“ Jan,Joe或Jane是罪犯吗?” 那么即使您将散列花了整整一分钟,枚举也将非常容易。除非整个游戏都牢记这一点,并且所有问题都极为开放,否则这将构成问题。但是,是的,如果您的问题开放式状态空间足够大,则可以保护答案。
克里斯·海斯

28

您有两个三个选择:

将答案与其他源代码分开

如果您希望代码是开源的,但是不希望答案是开源的,那么您可以在没有问题和答案的情况下将应用程序的代码开源,而问题和答案是一个单独的封闭源代码“插件”或数据文件。您的Android应用会将这两者捆绑到一个应用中。

将答案放在源代码中

或者,如果您认为问题和答案是您想要开源的核心部分,则应将答案放入源代码中,最好不要混淆,以便其他人可以阅读和修改它们。混淆源代码以致于无法理解和修改它与开放源代码的原理并不一致。

将答案放在互联网上的服务器上

通过以上两种解决方案,下载了您的应用的用户有可能在两种情况下都无需播放程序就能找到答案-不管您如何混淆/加密答案,如果程序可以在没有其他信息的情况下识别出答案,那么一个人可以检查您编译的应用程序。

如果您真的想确保没有人能找到答案,那么唯一的真实选择就是不给他们答案,而让应用程序在他们想知道答案时调用网络服务等。应用程序应发送用户输入的答案,网络服务应告知应用程序答案是否正确,这样,用户只有在获得正确答案后,才能知道答案是什么(简称Web服务的暴力破解,您可以对其进行检测和防御)。

如果您正在寻找使答案模糊不清的方法,那么这向我暗示您实际上并不想开源答案,因此您应该考虑第一种选择。

如果至关重要的是用户无法提前找到答案,那么第三个选择是您唯一的选择,但是我正在努力思考一个值得付出努力的情况,尤其是因为它阻止了用户在没有互联网连接的情况下使用您的应用程序。


8
Q&A甚至不必是一个插件,它可以是一个简单的数据文件。输入数据文件不一定包含在许可软件中,可以由其自己的单独许可证涵盖。只要您提供一个(不同的)示例数据文件与源代码一起使用,就不会妨碍对源代码或从所述源代码编译的程序的自由使用,因此,不应违反GPL。
Doktor J 2014年

我不确定这是否能真正解决他的问题-答案是经过加密和硬编码在代码中还是作为单独的文件分发,代码仍然需要能够解密答案,因此无论谁下载他的应用都可以做什么源代码确实可以得到答案。(除非它们被哈希化,如另一个答案所示)
约翰尼(Johnny

1
如果目标是检查答案并且不要求显示答案,则可以与使用单向哈希的密码相同。
JamesRyan 2014年

@Justin,感谢您的回答,您对它是否构成开源的评论很有趣。我认为隐藏答案并不是要混淆源代码或应用程序的工作方式,而是要保留挑战的完整性。事实证明,密码术是分发谜语的绝佳手段,而用户猜不到时(“是这个,是这个吗?”)而无需到处
乱扔

4

如果目标是使源代码不经意地使源代码散乱,但保持开放状态,以便其他人可以轻松进行自己的更改-例如,如果您将源代码发布为文字冒险,并且不希望出现任何描述性文字会构成破坏者,然后使用诸如rot13之类的可逆对象。

实际上,您可以腐烂所有翻译文件,然后快速将它们翻转回去。

保持开放精神。随机的“魔术”哈希并不是真正的程序员友好型。


4
请记住,我们当中的许多GeoCaching人士阅读rot13的程度几乎与原文一样流利。
2014年

4

开源要求源代码是公开的且可用的,而不是游戏数据。因此,您可以轻松地将数据放入另一个文件中,而不必发布该文件。如果要防止随意读取文件,请添加一些加密货币。我怀疑对于您的应用程序来说,强大的加密货币是必需的。


1
您可以在什么意义上“不发布”游戏数据?游戏必须能够访问该数据,以便拥有游戏副本的任何人都可以拥有该数据的副本。那几乎就是出版的本质:公开。
David Richerby 2014年

1
@DavidRicherby取决于您要发布和结束的内容。场比赛或你的引擎,可用于创建许多相似的游戏吗?允许人们操纵您的游戏,检查代码是否存在安全漏洞,或者只是重复使用组件?如果您的界面很简单,例如“带有问与答+程序的CSV =游戏”,那么我认为可以只发布程序,而不发布CSV。
拉斐尔

1
@Raphael但是分发由可执行文件和纯文本数据文件组成的游戏并不能达到将答案保密的目的。如果您想提出数据文件的加密版本,那很好,只要每个人都明白这只是出于安全考虑(密钥在源中)。但是,接下来我们要讨论的问题是,数据文件的纯文本是否构成了GPL的源代码,在这一点上,问题就变成了对GPL的解释,而不是计算机科学。
David Richerby 2014年

@DavidRicherby:同意。不过,尽管是IANAL,但我非常怀疑是否将包含谜语及其答案的数据文件视为程序中如此重要且不可替代的部分,因此无法单独获得许可-尤其是如果您在其中包含未加密的示例数据文件源代码分发,以及在必要时进行修改和加密的说明,以明确表明拥有源代码的任何人都可以创建自己的自定义数据文件,并将其与程序一起使用。
Ilmari Karonen 2014年

4

如果不想让用户知道答案,为什么还要将答案存储在GPL源代码中?即使它们现在不为人所知或容易破解,它们也可能(并且很可能会)在将来出现。

与其将它们存储在您的应用中,不如使用一个外部数据库。制作一个小型Web服务,将答案与数据库中的内容进行比较。然后,只要需要验证,就让您的应用程序对该Web服务进行调用。主要问题在于,由于它需要Internet访问,因此您将失去一些速度和潜在的用户群。您的应用许可应仅适用于应用本身,而不适用于网络服务。

您也可以将答案放入一个小的数据库中,然后将其放入程序中。据我所知,GPL仅适用于源代码,不适用于您的应用存储的任何数据。不过,我对此可能是错的。


1
“据我所知,GPL仅适用于源代码,不适用于您的应用存储的任何数据”。好吧,GPL说:“您必须根据本许可将整个作品作为一个整体许可给拥有副本的任何人。” 因此,您可能认为我们现在需要确定数据是否属于“整个工作”的一部分。但是实际上,当然,所有GPL的限制(包括该限制)仅适用于被许可人。许可人也应该遵守GPL的精神,这很好,但是他们不必担心版权警察的来访。
彼得·福特

1

请记住,即使将数据库存储在远程Web服务器中,也可以通过简单地写下所有已看到的正确键/值对来复制该数据库。通常来说,移动应用程序应尽量避免出现错误或由于网络中断而停止运行(使用排队消息传递,并“尽可能更新”)。

因此,如果您想要一个本地数据库,但不喜欢对其进行公然解密的想法,则可以使用Bloom过滤器(以避免与网络通信或在本地拥有较大的解密数据库)。这是拼写检查器过去在内存空间非常紧张时如何工作的方式。

因此,如果您将问题/答案对添加到过滤器中,例如:

哈希(NormalizeString(Question [n]))+哈希(NormalizeString(Answer [n]))

如果您询问“弗吉尼亚国会大厦?里士满”是否在集合中,它将回答“绝对不”或“几乎可以肯定”。如果误报太多,则使数据库更大。

假设用户将完全按照您的期望拼写“问答”,那么您可能会在一个很小的空间中拥有一个庞大的数据库。使数据库保持较小规模有助于进行更新,因为它们可能必须通过无线网络进行传输。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.