在厚客户端应用中保护API秘钥

4

在一个应用程序中,我有用于计算API调用哈希的密钥。在.NET应用程序中,使用类似Reflector的程序轻松地从程序集中提取信息以包含这些密钥。

混淆程序集是保护这些密钥的好方法吗?

4个回答

8

可能不行。

请了解加密和Windows内置的信息隐藏机制(例如DPAPI和将密钥存储在ACL受限制的注册表键中)。这是您需要在与应用程序相同的系统上保持安全性的最佳方法。

如果您正在寻找一种防止有人物理上坐在计算机前获取您信息的方法,请忘记它。如果有人决心并且可以无限制地访问未受您控制的计算机,则无法百分之百地确保数据在所有情况下都得到保护。如果有人想要获取数据,他们会尽力而为。


这很可怕,因为没有其他选择,但我必须同意,因为这是事实。 - Shimmy Weitzhandler

1
晚来一步......
在程序集/程序集配置文件中存储密钥的方法基本上是不安全的。没有可能的绝对方法可以将其存储为决心的用户将拥有访问权限。我不在乎你使用地球上最好/最昂贵的混淆产品。我不在乎你是否使用PDAPI来保护数据(尽管这更好)。我不在乎你是否使用本地操作系统受保护的密钥库(这甚至更好)。所有这些都不理想,因为它们都存在同样的核心问题:用户可以访问密钥,并且它们在那里,不变地存在着,可能持续几天、几周,甚至几个月和几年。
一个更安全的方法是使用经过验证的PKI来保护您的API调用。但是,如果您的API调用很繁琐,这显然会产生性能开销,但对于绝大多数应用程序而言,这不是问题。
如果性能是一个问题,您可以使用Diffie-Hellman算法通过非对称PKI建立共享秘密对称密钥,以便使用AES等密码进行加密。在这种情况下,“共享”意味着客户端和服务器之间共享,而不是所有客户端/用户。没有硬编码/内置密钥。任何地方都没有。
密钥是短暂的,每次用户运行程序时重新生成,或者如果您真的很偏执,它们可能会超时并需要重新创建。
计算出的共享密钥对本身仅在SecureString中存储在内存中。它们很难被提取,即使你这样做了,它们也只能在短时间内用于与特定客户端(即该会话)之间的通信。换句话说,即使有人黑掉了他们的本地密钥,它们也只能用于干扰本地通信。他们无法使用这些知识来影响其他用户,不像通过代码/配置共享的内置密钥。
此外,整个密钥本身从未通过网络传输。客户端Alice和服务器Bob独立计算它们。为了完成这项工作,他们传递的信息理论上可以被第三方Charlie拦截,允许他独立计算共享密钥。这就是为什么要使用(显著更昂贵的)非对称PKI来保护Alice和Bob之间的密钥生成。
在这些系统中,密钥生成往往与认证和会话创建耦合。您通过PKI“登录”并创建您的“会话”,完成后,客户端和服务器都独立拥有一个对于该会话中所有后续通信都可以使用的对数量级更快的加密的对称密钥。对于高规模服务器,这对于节省解密计算周期非常重要,而不是使用TLS来进行所有通信。
但是,等等:我们还没有完全安全。我们只是防止了读取消息。
请注意,仍然需要使用消息摘要机制来防止中间人操纵。虽然没有人能够读取正在传输的数据,但如果没有消息摘要,就没有任何东西可以防止它们进行修改。因此,在加密之前对消息进行哈希,然后将哈希与消息一起发送。服务器在解密时重新对有效载荷进行哈希,并验证它是否与消息中的哈希匹配。如果消息在传输过程中被修改,则它们不会匹配,整个消息将被丢弃/忽略。
需要保护的最后一个机制是重放攻击。到这个点上,你已经防止了人们读取你的数据和修改你的数据,但你没有防止他们简单地再次发送它。如果这对你的应用程序是一个问题,那么它的协议必须提供数据,并且客户端和服务器必须具有足够的有状态信息来检测重放。这可能是一些简单的东西,如作为加密有效负载的一部分的计数器。请注意,如果您使用的是UDP等传输方式,则可能已经有处理重复数据包的机制,因此已经可以处理重放攻击。
显然,要做好这件事并不容易。因此,除非您绝对不能使用公钥基础设施,否则请使用PKI。
请注意,这种方法在游戏行业中被广泛使用,因为高度希望每个玩家的计算量尽可能少,以实现更高的可扩展性,同时提供防止黑客/窥探的安全性。
因此,总之,如果这确实是一个问题,不要试图找到安全存储API密钥的方法。相反,改变您的应用程序如何使用此API(假设您自然地控制了双方)。使用PKI或使用PKI共享对称混合,如果PKI太慢(这在今天很少是问题)。那么您将不会存储任何安全相关的内容。

1
我认为这不会有什么影响,因为混淆(至少我理解的是这样)只是简单的改变方法名称,使代码难以理解(但并非不可能)。这不会改变实际密钥数据(我猜你已经在某个地方将它存储为常量了)。
如果你只想让它看起来更难一些,可以对明文运行一个简单的密码(如 ROT-13 或其他),这样它就不会明文存储在代码中。但这肯定不能阻止任何有决心的黑客访问你的密钥。更强大的加密方法也没用,因为你仍然需要将密钥存储在代码中,没有什么能保护它。
我唯一真正安全的想法是将密钥放在应用程序之外,并限制对其的访问。例如,你可以将密钥保存在一个单独的文件中,然后使用基于用户的操作系统级别的访问限制来保护该文件;那应该可以奏效。你可以对数据库连接做同样的事情(再次依靠基于用户的访问限制来防止未授权用户进入数据库)。
我曾经考虑过为我的应用程序做这件事,但从未实现过。

1
DannySmurf说得对,您无法将密钥隐藏在运行应用程序的人员视线之外;如果应用程序可以访问密钥,那么该人员也可以访问。
但是,您究竟想要实现什么?
根据您的目标不同,通常有其他方法可以实现,而不仅仅依赖于在用户机器上保持秘密。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接