【问题标题】:Using password as part of encryption key in Mobile - Server communication在移动 - 服务器通信中使用密码作为加密密钥的一部分
【发布时间】:2014-07-25 10:51:40
【问题描述】:

我目前正在开发一个移动应用程序,该应用程序附带一个使用 PHP 开发的 Web 服务。我们要确保的一件事是用户数据在所有可能的方面都是安全的。

经过仔细评估,我们决定将RNCryptor 用于所有与加密相关的事情。这是对 HTTPS 连接的补充。当前流程如下(登录示例):

  1. iOS 上的RNCryptor 库在将密码发送到服务器之前使用密钥对密码进行加密。
  2. 然后服务器将此加密密码存储在数据库中。
  3. 在重新认证时,应用程序发送密码(再次使用静态密钥加密),服务器对其进行解密(意味着服务器也有加密密钥),验证登录并发送登录密钥(使用相同的加密静态密钥)返回给客户端。
  4. 每个后续请求都依赖加密的 loginKey 和用户名来验证用户和登录会话的有效性。

我认为上述系统存在缺陷,因为 STATIC 加密密钥以及密钥在服务器和客户端上都可用。

我们希望通过将原始密码与 STATIC 加密密钥合并来使加密密钥动态化。这将使每个用户的加密密钥都是唯一的,但这也意味着服务器将不知道密钥。服务器必须知道密钥,因为其他用户数据也会根据此密钥进行加密和解密。

有人可以帮我解决这个问题吗?我需要采取哪些步骤来使系统更安全?任何特定于服务器-移动客户端的代码 sn-p 或参考链接也可以。我知道那里有很多教程,但大多数都将客户端恢复到基于 Web 的而不是移动的。

PS:抱歉发了这么长的帖子。

【问题讨论】:

  • 我不确定这是否是您正在寻找的东西,但这可以帮助您 - aws.amazon.com/articles/4611615499399490 - 功能原理可以为您提供想法
  • 这个问题似乎是题外话,因为它是关于defining/creating a security protocol
  • @owlstead,我既不想定义协议也不想创建协议。我要做的就是找出我们使用现有协议的正确方法。如果 SO 觉得它离题,请随意标记它。但答案是相关的并帮助了我。
  • 是的,但它也应该与未来的读者相关且不会混淆。目前,您似乎在这个问题中混合了实现和设计。如果您在 security.stackexchange.com 上询问与协议相关的问题并在此处询问与开发相关的问题,您 - 以及其他所有人 - 将获得更高质量的答案。否则,这是一个不错的话题,我没有投反对票或其他任何事情。

标签: php android ios security encryption


【解决方案1】:

我可能只会使用 OATH2 令牌进行身份验证,但如果您想按照自己的方式进行...

为了保护密码,使用了加盐哈希。作为使用盐散列密码的基本示例,请考虑以下内容,并记住它不是加密安全的。

shaResult = SHA1(16 Byte Random Salt | "p@ssword")

基础知识:服务器存储 shaResult。您的应用存储生成的盐值。当用户输入密码时,您将其附加到存储的盐中,对其进行哈希处理,然后将其发送到服务器进行验证。现在真的没有必要将它加密到服务器上。 HTTPS 连接应该可以处理。

Salted Password Hashing - Doing it Right 详细描述了良好的加密密码散列,总结一下,他们建议使用以下内容:

  1. Salt 应使用加密安全伪随机数生成器 (CSPRNG) 生成。多种编程/脚本语言的链接中提供了建议的 CSPRNG。
  2. 盐必须是每个用户每个密码唯一的。每次用户创建帐户或更改密码时,都应使用新的随机盐对密码进行哈希处理。切勿重复使用盐。盐也需要很长,以便有许多可能的盐。根据经验,让你的盐至少与散列函数的输出一样长。 salt 应与哈希一起存储在用户帐户表中。
  3. 使用经过充分测试的加密哈希算法,例如 SHA256、SHA512、RipeMD、WHIRLPOOL、SHA3 等。
  4. 使用执行多次迭代的慢速散列函数。标准算法包括PBKDF2bcrypt
  5. 使用键控散列算法HMAC

我要重申,安全连接仍需要与上述内容结合使用。

【讨论】:

  • 谢谢!这些链接有帮助(尤其是第二个)!!
  • 投了反对票,因为这个答案明确忽略了第二个链接中给出的建议。它也远不是给定问题的完整解决方案。
  • 因为我的示例使用 SHA1 而不是 SHA256?
  • 只有当评论作为答案输入时,我才会将评论标记为正确答案。无论哪种方式,感谢 @raz 和 @Mihai Andrei Rustiuc 的宝贵意见。我已经找到了使用散列和 RNCryptor 的正确方法。
  • 否,因为您的示例不使用 PBKDF(基于密码的密钥派生函数)来执行散列。您使用了盐,但没有迭代计数或工作因子。已知的 PBKDF 是 PBKDF2、bcrypt 和 scrypt。另请注意,您知道用于密码的编码(但这也适用于密钥派生函数)。
【解决方案2】:

如果您想要一种每次都不使用相同身份验证值的方法,请考虑使用防止重放攻击的Challenge-Handshake Authentication Protocol。更多完整详情请参阅RFC1994

在设置时,客户端和服务器之间会建立一个共享密钥。这必须通过 SSL 或旁通通信安全地完成。

身份验证:

  1. 服务器向客户端发送随机质询。
  2. 客户端使用挑战值通过 PBKDF2 等函数计算哈希,并将其与用户标识符一起发送到服务器。
  3. 服务器执行相同的计算并验证其用户标识符/共享密钥表中的值。

略有不同,但概念相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-02
    相关资源
    最近更新 更多