【问题标题】:authentication method身份验证方法
【发布时间】:2010-10-24 12:16:01
【问题描述】:

我正在编写一个服务器-客户端应用程序来接收用户消息并发布它。

考虑认证方法。

  1. 非对称加密,可能是 RSA。
  2. 哈希(salt+password+'msg'+'userid'),SHA256
  3. HMAC,SHA256。似乎比方法 2 更安全。还涉及对密码和 msg 数据进行哈希处理。
  4. “msg”的对称加密,两侧都存储有静态密码,可能是 AES。

不需要加密,因为无论如何都会在线发布味精。所以我更倾向于 HMAC 或 PKI 方法。

我正在使用 java 发送请求(包括要实现的任何身份验证方法) www.mysite.com/foo?userid=12345&msg=hello&token=abc1234

python 在服务器端接收请求并确保请求来自有效用户。

问题在于集成并确保双方都了解彼此的身份验证令牌。这对我来说是一个很大的因素。并且还考虑了两种语言的可用库的可用性。

或者我可以选择将服务器端重写为java。 (为什么不是python?客户端应用程序需要在java中)

你怎么看?


编辑:我不会将其视为 Web 应用程序。该应用程序不提供任何网页。大多数操作与网络无关。只是客户端-服务器通信通过互联网。我认为通过 HTTP 发送 POST/GET 是一种更简单但不安全的方式。随时向我建议任何其他选择。

SSL 是一种安全的加密方式。但它并不能阻止攻击者以用户身份向服务器发送消息。任何人都可以发起 HTTPS 连接。并且通信的内容不需要加密。无论如何,它将由服务器在线发布。我需要的是一种对消息和发件人进行身份验证的方法。

目前我倾向于使用 HMAC 算法。 RSA 会更安全,但它也伴随着更多的开发人员努力。看看情况如何。

谢谢。

【问题讨论】:

  • HTTP Digest 认证有什么问题?为什么不使用已有的东西?它使用 hash+salt+nonce。

标签: java python authentication encryption hash


【解决方案1】:

您不能只使用标准 SSL 套接字来保护连接,使用密码验证用户,然后发送要发布的消息吗?如果客户端不多,您甚至可以使用自签名证书并将其放在客户端应用程序的 KeyStore 中,这样您就不需要从 Verisign 或其他任何人那里购买证书。

如果您将用户的密码哈希存储在服务器上(我认为您应该否则您将如何验证用户的密码),那么您可以首先在客户端重现该哈希(假设您哈希用户+ pass) 然后将其附加到消息并散列结果。您将用户 ID、哈希和消息发送到服务器。

在服务器端,您收到一个带有用户 ID 的请求,您检索用户的密码(服务器只存储了 user+pass 的哈希值),您将其附加到消息并再次对其进行哈希处理,然后将其与请求中的哈希。如果匹配,用户可以发布消息。

哦,您应该使用 HTTP POST,而不是在 URL 上发送数据。服务器不应接受发布请求的 URL 上的数据。

【讨论】:

  • 好吧,我稍后会研究 SSL。我想知道在 python 和 java 上实现这个有多么困难。不管怎么说,还是要谢谢你。 =)
  • 转念一想,SSL 不是我所需要的。我需要验证客户端用户的身份,而不是保护内容免受窃听。无论如何,该消息将在线发布。
  • 哈希用户+密码+消息是我想到的,但似乎不如HMAC算法安全。所以这就是我目前的目标。
【解决方案2】:

好的,首先,要考虑的一个选项是走“企业解决方案”路线并购买标准 PKI 市场:为自己购买 Veri$ign 等的证书并使用无聊的旧 HTTPS(或至少 TLS,底层协议)。然后从客户端发送数据(或多或少)是一件轻而易举的事,并且在您选择的任何语言中都会有一个标准库来解释另一端的事物。实际上,我认为 HTTPS/TLS 和整个证书基础架构对于您知道正在与哪个服务器通信并且知道要使用哪种加密系统的应用程序来说是一种复杂的空间浪费。但是“开箱即用”的库的可用性意味着它可能让您快速启动并运行,因此绝对值得考虑一种或另一种方式。

原则上,您不需要 PKI 颁发的证书即可使用 HTTPS/TLS。但在实践中,花几美元可能比尝试说服标准库接受自发证书更容易。 (一般来说,使用 HTTPS 库可能只是意味着您最终将 2 天的“编程我的加密系统”问题变成了 2 天的“为什么这个黑匣子不接受我的证书”问题——这也有点取决于你想解决什么问题...)

即使您不使用 HTTPS/TLS,您也可能需要通读规范,以了解它如何克服某些安全威胁(以及这些威胁是什么)。

好的,那么就拿你的观点来说吧:

  • 需要明确的是,您不需要证书或 PKI 即可使用 RSA 或其他非对称加密。 PKI(尝试)解决了客户端需要与“神秘”服务器对话的问题,当该服务器说“这是我的公钥”时,它无法信任该服务器。如果您正在编写一个专用客户端并且您事先知道您正在与哪个服务器通信,那么您可以将公钥分发给您的客户端。客户端知道它正在与正确的服务器通信,因为如果不是,该服务器将无法理解它使用该公钥加密的内容。
  • 在使用“原始”哈希时需要注意的主要事项是它们容易受到扩展攻击。因此,如果您发送“a|b|c”加上该数据的哈希码,攻击者可以计算出“a|b|c|d”的哈希码(因此在您的示例(2)中,他们可以替换为“ userid" 为 "useridX" 并根据你为 "a|b|c" 提供的散列码计算出一个新的散列码)。 HMAC 方案解决了这个问题。
  • 无论如何,如果您使用“原始”加密工具,仍然使用标准库,因为它们会考虑一些安全问题。例如,对于 RSA,您必须小心使用填充(请参阅我在 RSA encryption in Java 上写的一些信息以及它所在的密码学部分——这对您来说可能很有趣)。在生成任何加密密钥时,您需要注意“随机数据的来源”。
  • 您不必将 AES 加密密钥基于密码(如果您这样做,请阅读基于密码的加密方案:密码通常几乎没有熵,因此您需要采取额外措施来尝试防止这种情况)。但我会采用更标准的方法,即使用密码验证连接,并且作为验证的一部分,协商随机 AES 密钥。
  • 确保您正在解决方案中的重放攻击问题(通常,客户端和服务器应在通信开始时相互发送一个随机“nonce”,并且身份验证和未来通过该连接进行的通信将取决于随机数)。

【讨论】:

    【解决方案3】:

    让我在您的提案中添加一些随机想法/cmets。

    1. RSA:由于您主要对身份验证感兴趣,我假设您希望使用 RSA 签名。这意味着每个用户都需要自己的私钥。对我来说,这听起来有点矫枉过正,尤其是当用户和服务器已经共享共同的秘密(即密码)时。
    2. 使用 SHA256 是一种很好的方法。我有一些问题要理解为什么要包含盐,因为通常使用盐来避免攻击者预先计算字典的哈希值。需要明确的是:字典攻击在这里是一个问题。攻击者可以尝试使用字典中的所有密码对消息进行哈希处理。只是他必须为每个用户重复这种攻击,并且不能重用预先计算的值。一种使这种攻击稍微有点的方法 更困难的称为关键加强,例如通过反复散列结果 n 次 从而迫使攻击者在字典攻击期间执行更多工作。
    3. 我完全同意 HMAC 比 SHA-256 更好。毕竟 HMAC 是为身份验证而设计的。我不确定为什么要在计算 HMAC 之前对消息进行哈希处理。 HMAC 会为您做到这一点。
    4. 加密并不总是提供身份验证。这尤其适用于攻击者学习明文的情况,就像他在您的情况下所做的那样。他也许能够利用加密模式的特性来操纵密文,并确切地知道得到的明文将是什么样子(例如,CBC 模式允许这种操纵)。您之前的提案 (HMAC) 更可取。

    最后,如果您可以像其他人建议的那样在用户和服务器之间建立 SSL 连接:这将是一个更安全的解决方案,因为即使是上面提到的字典攻击也不可能。

    【讨论】:

      【解决方案4】:

      RSA 协议通常用于设置密钥交换以实现更快的加密方式。这就是 SSL 的工作原理。

      如果您的应用程序的安全要求如此敏感以至于您需要 PKI,那么应该说(无意苛刻)如果您需要在 SO 上询问它,那么它可能是您不应该做的事情尝试去做(鉴于对安全通道的成功攻击通常会攻击实施的弱点)。

      正如 Chochos 所建议的那样,简单地使用 Java 中现有的 SSL 基础设施和您的服务器来设置安全的 https 连接,然后简单地将用户密码从客户端传递到服务器有什么问题?

      【讨论】:

      • 对“PKI”一词感到抱歉。通过 PKI,我的意思是非对称加密,而不是使用证书颁发机构等的完整获取实现。我认为我的应用程序不够敏感,不需要 Verisign 证书。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-29
      • 1970-01-01
      • 2018-08-03
      • 2023-04-07
      • 2015-08-18
      • 1970-01-01
      相关资源
      最近更新 更多