通过HTTP验证用户(而不是HTTPS)

时间:2010-08-25 19:15:54

标签: security cryptography public-key-encryption

INITIAL NOTE:这仅适用于个人修补项目;我不是在这里写企业安全,如果我是,我知道比尝试编写我自己的方案更好。 :-D

编辑:为了强调上述观点,我试图在“iKnowThisWouldBeABadIdeaInRealLife”下标记这个,但是因为它是> 25个字符所以不会接受它。请注意,我知道它不是商业级的!

我需要一种通过HTTP验证用户的方法(在这种情况下不能使用HTTPS)。我需要知道另一端的人真的是他们所说的人(对某种程度上相当高的信心)。一旦我确定用户是合法的,如果客户端和服务器之间的内容以明文形式发送,我不在乎

我正在考虑的问题是尝试从客户端向服务器发送密码而不将其作为纯文本发送。我已经考虑过在javascript中尝试一些公钥加密,因为一些谷歌搜索已经发现了一些看起来很有趣的库。

以下是我正在考虑的方案:

(假设 A A'分别代表私钥和公钥;还有 enc(文字,密钥) dec(密文,密钥)代表加密/解密函数)

    +------------------------+------------------------------+
    |         SERVER         |            CLIENT            |
    +------------------------+------------------------------+
(1) | t = randomToken()      |                              |
(2) | enc(t, A)           -------->  c                      |
(3) |                        |       A' = getKeyFromUser()  |
(4) | p                 <--------    p=dec(c, A')           |
(5) | if (t==p)              |                              |
    |     allowAccess()      |                              |
    | else                   |                              |
    |     denyAccess()       |                              |
    +------------------------+------------------------------+

我看到的一个弱点是,正在听交换的坏人,虽然他没有 A ,现在有一个已知的密文/明文组合,我记得从加密class是 BAD IDEA 。我觉得有些腌制可能会以某种方式减轻这种情况吗?

所以这是我的[两个]问题:

  1. 这是一个'好'的计划吗? (请记住,如果此初始交换之后的任何内容都是纯文本,我不会关注 - 我只是在这里尝试验证初始身份)
  2. 解决上面提到的“已知明文/密文对”弱点的最佳方法是什么?盐析?
  3. 谢谢!


    编辑:感谢所有讨论!只是为了澄清:

    • 我并不担心向客户保证SERVER是他们所说的人。只有相反(确保客户端的服务器是他们所说的人)
    • 我知道MITM攻击。该计划并非旨在防范它们。
    • 我知道已经存在很多解决方案。这对我来说纯粹是一次学习练习!我不是要重新发明轮子或建立一个更好的捕鼠器。这只是为了好玩!
    • 以下是我对该计划的思考过程:(我知道我并没有正确地使用公钥与私钥,但请耐心等待一段时间)

      • 鲍勃走向爱丽丝说:“嘿,我是鲍勃。”

      • Alice说,“好的。我知道Bob的'私钥'。如果你真的是Bob,请把这个秘密消息我加密(用Bob的私钥),并为我解密。”

      • 鲍勃回复了正确的信息,爱丽丝很高兴。

6 个答案:

答案 0 :(得分:3)

您可以使用HTTP Digest Authentication。大多数浏览器,服务器和各种库已经支持这一点。

修改

如果你真的想在没有SSL / TLS的情况下使用一些公钥加密,你可以查看HTTPsec

如果你真的想要发明自己的身份验证方案,你应该注意你的加密/解密错误你的标签(不确定它是否是一个错字,或者我可能没有正确阅读图表,它看起来像你正在服务器端做 enc(t,A)):

  • 使用公钥进行加密
  • 您使用私钥解密
  • 您使用私钥签名
  • 使用公钥验证签名

在您的方案中,您需要服务器发布其公钥并让客户端使用它来加密其答案,然后将其发送到服务器,然后服务器可以使用其私钥对其进行解密。那么困难在于确保公钥确实是合法服务器的公钥,并且它没有被中间的攻击者拦截和替换:这就是PKI和证书在TLS(和HTTPS)中发挥作用的地方。

答案 1 :(得分:2)

如果你使用适当的填充机制(如OAEP)使用RSA,它就不容易受到已知明文攻击。所以没有必要绕过它。

一个陌生人走了过来,声称自己是鲍勃。为证明这一点,他们证明了他们只知道真正的鲍勃所知道的秘密。在公钥加密中,秘密是私有密钥。

在您的提案中,您首先必须获取Bob的公钥,并确保它真的是Bob的,以便以后您可以使用它来加密挑战。你如何引导这个过程?

现在“Bob”正确回应了您的挑战,并对他的请求提出了一些指示。你怎么知道,中间的女人,夏娃,没有砍掉鲍勃的真实指示并替换她自己的指示?

这是一个糟糕的方案,并没有接近提供安全性。

如果您打算继续这样做,您应该考虑以数字方式签署请求的方法。例如,POST一个数字签名的数据块。所有HTTP级别的信息都被丢弃为不可信任的,只有数字签名的消息的内容才会被执行。

答案 2 :(得分:1)

你基本上想在HTTP上实现SSL;这有点可行,但永远不会像真实的那样好。

能够来回发送加密数据只是问题的一半。问题的另一部分是确保您实际上正在与服务器通信(想想中间人攻击中的人)。

我不确定SSL是如何工作的,但这是要走的路。你应该读一下。从你的计划来看,它似乎毫无意义。为什么要将明文发送回服务器?这违背了建立这个目的的目的。

以下是我将如何做到这一点:

  1. 服务器向客户端发送随机令牌。服务器将令牌存储在“挂起”列表中。这些可以在某个时间间隔内清除(例如:每15分钟一次)
  2. 客户端将enc(comb(username, password, token), pubKey)发送回服务器,其中comb()是一个结合了用户名,密码和随机令牌的功能。
  3. 服务器使用decomb(dec(message, privKey))获取用户名和密码,其中decomb()comb()的倒数。
  4. 服务器检查令牌是否存在于挂起列表中。如果不是,请拒绝登录尝试。如果是,服务器可以像往常一样继续执行身份验证。
  5. 如果生成的令牌永远不会重复,攻击者不能只重新发送相同的加密消息,也不能解密消息以找出所有内容。

答案 3 :(得分:1)

假设您的客户端和服务器在此交换开始之前交换公钥,您可以执行以下操作:

  1. 客户端使用包含用户名和加密(私钥,用户+ URL)的标头发送HTTP请求
  2. 服务器尝试使用指定用户的公钥解密标头的内容。
  3. 如果解密失败,或者所包含的用户或URL不匹配,则拒绝该请求。
  4. 包含URL以防止针对不同资源的重播攻击。通过在加密数据中包含时间戳,可以获得更高的重放安全性。

    如果使用质量加密方案,已知的明文攻击不是一个大问题。

    编辑:删除了AES128的提及。

答案 4 :(得分:0)

就像布鲁诺说的那样,你所描述的是HTTP摘要,这是非常安全的。但是如果你读到它就会有循环漏洞。不大。有人真的必须在等待拿起握手中的钥匙以便能够闯入。如果安全性是一个问题,你必须使用https并让位。这就是它的原因。 https拥有证书,可以在一开始就使握手能够抵御窃听者。

答案 5 :(得分:0)

首先,HTTPS不仅仅是加密。它还可以防止活动的MTIM攻击并保护您的会话ID。如果您只是溢出会话ID,则密码无意义。这是OWASP A9的一部分。

但是,有人实施了JavaScript solution。其中加密会话ID和密码。它使用Diffie-Hellman密钥交换,类似SSL。甚至作者都说它不是https的好替代品,但总比没有好。我甚至不会考虑使用除https之外的任何东西。