首页 文章

如何保护移动应用的API(私钥)

提问于
浏览
12

我正在构建一个必须只能用于iOS应用程序的Web服务 . 在未来,我想扩展到一个移动网站,使我的服务也可用于其他移动操作系统 .

现在,我通过API完成所有工作 . 我的用户可以注册,搜索公司,从这些公司订购产品并跟踪他们的订单 . 它尚未活跃,但它正在运作..

我面临一个主要问题:如何确保这一点?

在过去的几天里,我已停止编码,我一直忙于搜索网络,StackOverflow和信息安全,以了解如何执行此操作 . 我发现亚马逊获取API的方式对我来说是最好的解决方案 . 亚马逊确保其服务的方式解释here . 我已经为我的服务稍微调整了一下:

  • 用户注册并获取私有API密钥公共(标识)密钥

  • 用户输入凭据并点击"log in" . 应用程序从变量私钥中创建哈希 . App将变量时间戳哈希公钥发送给API

  • API在数据库中查找公钥,查找属于该公钥的私钥(如果公钥有效) . 然后API以与应用程序相同的方式创建哈希 . 如果哈希值相同,则执行请求(在这种情况下登录) .

这种保护服务的方式对我来说很有意义,我可以编写大部分代码 . 但我有一个主要问题,我找不到任何解决方案:

  • 用户在创建帐户时获取公钥和私钥API密钥 . 公钥可以从服务器发送到用户设备,因为这不一定是秘密 . 由于私有API密钥可以通过网络发送, how on earth can I make sure that an account logged in on a user's device knows the private API key that is created on the server?

有谁知道如何解决这个问题?任何帮助将非常感谢!!

3 回答

  • 5

    我认为你的身份验证方案过于复杂 . 我建议使用像oauth2这样广泛使用的协议来保护你的API - http://oauth.net/2/ .
    有许多客户端库和许多服务器端插件支持和实现它,并且可以轻松集成到您的应用程序中 .

  • 1

    以下是我解决同样问题的原因以及为什么我认为您的实际问题与您认为的问题不同:

    亚马逊的做法有道理,安全,并且比oAuth更容易实现,所以我不确定为什么每个人都建议使用它 . 我使用亚马逊方法,如下所示:

    • 用户注册使用API . 我们确保生成公钥,密钥并保存联系人电子邮件,角色(我们的角色为"admin"和"user"),然后将API用户的 status 设置为活动状态 . 这允许我们在服务器上管理基于角色的权限(速率限制,访问控制等)并随时停用帐户

    • 我们 send the client ID and secret key back to the client . 没有办法绕过这个,所以你通过以下方式使其尽可能安全:

    • 仅发送一次令牌 . 如果用户忘记了他们的令牌,他们需要注册一个新的API客户端

    • 确保 all requests are made over HTTPS ,没有例外 - 这使得任何嗅探流量都被加密,攻击者只有一次拦截

    • 加密数据库中的令牌 . 不要哈希它,因为它需要是可逆的 . 如果您使用AES-256加密时安全地存储加密密钥并生成新的随机IV(初始化向量),则攻击者将无法检索客户端密钥(理论上,如果您正确保护该密钥,即使不是它花了你一些时间来停用受损的客户端令牌) . 您在生成时将纯文本令牌发送到客户端,但在它到达数据库之前对其进行加密 .

    • 当客户端发出请求时,他们会发送标头和已签名的请求 . 在您的服务器上,您可以找到与客户端ID关联的加密令牌,对其进行解密,然后计算签名并将其与发送的内容进行比较 . 如果您的计算签名和他们的签名匹配,那么您将继续请求 .

    就像我说的那样,没有办法将私人令牌发送给客户端,但好处是你只做了一次,而且无论如何都应该通过SSL .

    The problem you're missing is how to protect that token on the device itself. 那是's another problem that I haven'看到任何解决方案 .

    这两种情况唯一可行的选择是:

    • 您在服务器上为每个客户端生成一次私有令牌,并且只将其一次性发送到客户端(没有提醒,只有像Amazon这样的总重置)

    • 除了将令牌存储在设备本身之外,你真的无能为力 .

    一我们想出的用于确保设备上的令牌的措施是实际上定期旋转令牌 . 因此,例如,您可以将令牌存储在设备上,供每个用户使用,也可以硬编码到应用程序中 . 您经常需要为设备添加新令牌 . 如果您有一个硬编码令牌,那么您使用新的硬编码令牌更新应用程序,当用户通过他们的应用商店更新时,他们将自动获得新令牌 . 然后撤销所有X天的令牌并要求任何落后者更新应用程序 . 如果每个客户端在登录/注册时被赋予唯一令牌,则另一个选项是使令牌失效,然后在下次使用应用程序时自动将其注销 . 重新登录后,您将生成并发送一个有效期为X天的新令牌 .

    最后,这些是常见的一些问题,至少对于您正在使用的身份验证方法,我认为我还没有解决 . 因此,您真正做的最好的事情就是接受与发送和存储令牌相关的小风险,并将精力放在使API安全上 .

  • 5

    正如Rotem Hermon建议我也将实施Oauth2 .

    关于“我怎样才能确保用户设备上登录的帐户知道在服务器上创建的私有API密钥?”问题,(在一个非常抽象的层面)服务器确认客户端通过私钥的签名计算知道私钥 .

    一个愚蠢的抽象例子:

    服务器具有私有客户端密钥(“Z”)客户端具有其私钥(“Z”)

    他们都知道他们的公钥(“Y”)

    客户端将请求哈希到资源("A")以及他的私钥和公钥,以使用类似这样的函数对请求进行签名 signMyRequest(request,publicKey,privateKey)

    在这个例子中将 signMyRequest("A","Y","Z")

    公钥将符合'username'的作用,私钥将符合'password'的作用 . 不同之处在于您不将其传递给服务器,AWS只是对私钥进行计算 . 查找AWS Signature V4以获取更多信息:http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

    希望这有助于并将其作为功能的抽象示例 .

    抛开身份验证和授权,您还应该关注SQL注入,XSS等常见的安全漏洞,因为它也是Web应用程序,并且大多数常见的安全漏洞都适用 .

相关问题