在源代码中隐藏API密钥的最佳方法


12

我需要一些有关如何保护应用程序(尤其是ac#.NET应用程序)中的私有API密钥的想法。

首先,我了解到从理论上讲不可能在源代码中隐藏任何内容,因此我想出了另一个想法,但是我不确定它的合理性。无论如何,是否有可能以某种方式与Web服务器通信以验证私钥,然后再与应用程序对话以确认它是合法的握手?

我有两个密钥可以使用:一个公共密钥(顾名思义,不必像对待私有密钥一样小心对待),以及一个私有密钥,它需要与他人保持安全。

我将如何做到这一点的任何想法将不胜感激。


4
您是否要阻止有权访问已部署的二进制应用程序的人读取密钥(正如您的标题所暗示的那样),或保护他们不要对其进行修改(如您通过服务器进行验证的想法所暗示的那样)?最终的最终目标是什么?
gregmac 2014年

3
为不熟悉它的读者概述API密钥的概念可能是有益的。API密钥是授予与服务(通常是Web服务)交互的某些软件的开发人员的秘密。它用于识别流量来源,解除限制与匿名访问,并向密钥所有者收取服务使用费。您应该将其适当地隐藏起来,如果受到破坏,最好将其撤消。由于需要将其完全传达给服务,因此您总是会迷失方向。
拉尔斯·维克伦德

@gregmac是的,我正在尝试阻止应用程序的第三方用户读取密钥。
斯宾塞

不要放在那儿
CodeART

Answers:


14

总结一下:

  • 您拥有供应商发布给您的API密钥,因此您可以使用他们的API,并且您有义务防止其他人知道此密钥。
  • 您正在应用程序代码中调用该供应商的API(需要API密钥)
  • 您正在将应用程序部署到客户可以访问二进制文件的系统,从而可能对代码进行反编译/反混淆或拦截流量

防止损害此密钥的最佳方法是对其进行控制。这意味着永远不要将其部署在服务器上,在该服务器上,除了您之外的任何人都可以读取二进制文件,也不要通过您无法控制的通信链接。

最终,如果二进制文件不受您的控制,则二进制文件中的所有内容都将不受您的控制。同样,如果有人可以拦截流量,则他们可以捕获API密钥(即使您正在使用SSL,也有可能)。

我可以看到两种主要方法来完成此操作,这两种方法都不会在已部署的应用程序中包括您的私有API密钥:

为每个部署获取唯一的API密钥

这将需要与供应商建立一些额外的关系,您可以在其中获得密钥或让客户获得密钥。

实际上,例如对于使用Google Maps API的产品,这是相当普遍的。该软件的创建者在开发/运行其副本时会使用自己的密钥,但他们并未将其包含在软件中,而是要求您(作为安装该软件的用户)进入Google并获取您自己的API键。该软件仅具有配置选项以设置要使用的Google Maps API密钥。

实际上,许多签发API密钥的供应商都要求您以这种方式进行操作,因此无论如何您都可能走错了路,这可能是您根据供应商的服务条款和/或您可能与他们签订的任何法律合同。

使用代理

设置代理API,您的应用程序在服务器上调用您的API,然后,您的API使用密钥调用供应商的API。

您可能需要对API进行其他保护,例如,确保仅您的应用程序正在使用它。这可以通过以下方式完成:

  • 使功能如此具体,但您的应用程序可以使用它
  • IP白名单
  • 您的服务器已经具有一些现有的许可/授权机制
  • 您自己的API密钥系统,您可以在其中向客户发布密钥

这里要记住的是,您可能不被允许这样做。您的供应商可能具有服务条款或法律合同,阻止您构建“聚合服务”或代理,因此您需要进行检查。


处理不当行为

即使您的密钥没有受到破坏,如果您的一位客户正在做的事情导致供应商封锁您的密钥,您的所有客户也会突然被禁用,而您唯一的解决方法就是更新其他所有用户。

同样,如果想阻止一个客户(例如,他们停止付款,盗版软件等),那么您必须在不向其他人发布更新然后禁用密钥的情况下才能这样做。

除了少数客户之外,任何其他人的后勤工作将很快变得站不住脚。

无论您是代理还是每个安装都有唯一的密钥,您都可以相对轻松地处理任何一种情况(对其他任何人几乎没有影响)。


尝试在将密钥嵌入到您的软件中时保护密钥最终是徒劳的。无论您做什么,任何有权访问二进制文件,源文件和/或通信通道并确定有足够能力掌握其关键点的攻击者都将能够这样做。

所以不要嵌入它。“唯一的制胜法宝是不参加比赛。”


2
为“为每个部署获取唯一的API密钥” +1。甚至可以与代理服务器结合使用,从而为您提供了一个禁用顽皮键/客户端的[有限]功能。
svidgen 2014年

@svidgen非常好,我添加了一个讨论这一部分的内容。谢谢。
gregmac

1
+1,通用密钥几乎总是会在***中咬你
Wyatt Barnett 2014年

非常深入的回应。不幸的是,我只分配了一个私有API密钥,因此无法要求用户提取密钥,因为我处于使用网络协议的NDA之下,因此是私有密钥的原因。代理可能也出了问题。我可能只是不得不以某种方式将其转换为非人类可读的格式,并将其放置在源代码中的某处-不是一个很好的选择,但是没有太多选择。
斯宾塞2014年

@Spencer“代理可能也出了问题”为什么?这似乎很荒谬,分发密钥也可能会违反您的NDA。
安迪

5

如果目标代码中有键,则根据定义它是公开的。围绕混淆器的黑客会迅速反编译目标代码。私钥将在目标代码之外,并在另一个文件中。困难的部分是向用户提供此私钥。提供私钥后,您可以使用附加在文件末尾的私钥签名和应用程序中的公钥来验证私钥的完整性。如果您拥有安全的通信通道,Web服务器也可以执行此验证。

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.