5

初始说明:这仅适用于个人修补项目;我不是在这里写企业安全,如果我是,我会知道最好不要尝试编写自己的方案。:-D

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

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

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

这是我正在考虑的方案:

(假设AA'分别代表私钥和公钥;另外,enc(text, key)dec(cyphertext, key)代表加密/解密函数)

    +------------------------+------------------------------+
    |         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()       |                              |
    +------------------------+------------------------------+

我在这方面看到的一个弱点是,正在收听交换的 BAD GUY,虽然他没有A,但现在有一个已知的密文/明文组合,我记得在加密课程中是BAD IDEA。我想一些盐可以以某种方式缓解这种情况?

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

  1. 这是一个“好”的计划吗?(请记住,我不在乎此初始交换之后的任何内容是否是明文 - 我只是在这里尝试验证初始身份)
  2. 解决上述“已知明文/密文对”弱点的最佳方法是什么?盐?

谢谢!


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

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

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

    • 爱丽丝说:“好的。我知道鲍勃的‘私钥’。如果你真的是鲍勃,请拿走我刚刚加密的这条秘密消息(用鲍勃的私钥),然后为我解密。”

    • Bob 回复了正确的消息,Alice 很高兴。

4

6 回答 6

3

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

编辑:

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

如果您真的想发明自己的身份验证方案,您应该注意您的标签的加密/解密错误(不确定是否是拼写错误,或者我没有正确阅读图表,看起来您是在服务器端执行enc(t,A) ):

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

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

于 2010-08-25T19:18:53.110 回答
2

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

一个陌生人走上前来,自称是鲍勃。为了证明这一点,他们证明他们知道只有真正的 Bob 知道的秘密。在公钥密码学中,秘密就是私钥

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

现在“鲍勃”正确地回应了你的挑战,并根据他的要求添加了一些指令。你怎么知道中间女人 Eve 没有砍掉 Bob 的真实指令并用她自己的指令代替?

这是一个糟糕的方案,并不能提供安全性。

如果您要追求这一点,您应该寻找对请求进行数字签名的方法。例如,POST 一个经过数字签名的数据块。所有 HTTP 级别的信息都被视为不可信而被丢弃,并且仅对数字签名消息的内容进行了处理。

于 2010-08-25T20:27:32.720 回答
1

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

  1. 客户端发送带有包含用户名和加密(私钥,用户+ URL)的标头的 HTTP 请求
  2. 服务器尝试使用指定用户的公钥解密标头的内容。
  3. 如果解密失败,或者包含的用户或 URL 不匹配,则请求被拒绝。

包含 URL 是为了防止针对不同资源的重放攻击。通过在加密数据中包含时间戳可以获得更高的重放安全性。

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

编辑:删除了对 AES128 的提及。

于 2010-08-25T19:29:46.857 回答
1

您基本上想在 HTTP 上实现 SSL;这在某种程度上是可行的,但永远不会像真实的那样好。

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

我不太确定 SSL 是如何工作的,但这是要走的路。你应该读一读。从您的计划的外观来看,这似乎完全没有意义。为什么要将明文发送回服务器?这违背了设置此设置的目的。

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

  1. 服务器向客户端发送一个随机令牌。服务器将令牌存储在“待处理”列表中。这些可以在某个时间间隔内清除(例如:每 15 分钟)
  2. 客户端发送enc(comb(username, password, token), pubKey)回服务器,其中comb()有一些结合了用户名、密码和随机令牌的函数。
  3. decomb(dec(message, privKey))服务器使用wheredecomb()的倒数取回用户名和密码comb()
  4. 服务器检查令牌是否存在于待处理列表中。如果不是,则拒绝登录尝试。如果是,它的服务器可以像往常一样继续执行身份验证。

如果生成的令牌从不重复,攻击者就不能只是重新发送相同的加密消息,也不能解密消息以找出所有内容。

于 2010-08-25T19:23:46.587 回答
0

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

但是,有人已经实现了JavaScript 解决方案。它加密了会话 ID 和密码。它使用类似于 SSL 的 Diffie-Hellman 密钥交换。甚至作者都说它不是 https 的好替代品,但总比没有好。我什至不会考虑使用 https 以外的任何东西。

于 2010-08-25T19:48:11.783 回答
0

就像布鲁诺所说的那样,您所描述的内容与 HTTP 摘要类似,这是非常安全的。但是,如果您阅读它,就会发现有环路。不大。真的必须有人在听,等着拿起握手中的钥匙才能闯入。如果安全是一个问题,你必须使用 https 并为此让路。这就是为什么它在那里。https 具有证书以使握手一开始就可以抵抗窃听者。

于 2010-08-25T19:31:43.717 回答