【问题标题】:AES encryption & security flawAES 加密和安全漏洞
【发布时间】:2013-12-02 09:45:24
【问题描述】:

检查更新#1

此逻辑是身份验证过程的候选者,由简单的 HTTP 请求完成:

  • 我正在发送:userName + encrypted_userName(encrypted_userName 实际上是 userName 的加密结果,使用 AES 完成 & 作为密钥,我使用密码的 md5 哈希)。注意:我不会发送 md5 哈希密码。
  • 在我比较的服务器上:encrypted_userName 和 own_encrypted_userName(因为在服务器上我可以访问用户的完整信息,所以我计算自己的 encrypted_userName)。

问题:这是一个安全漏洞吗?假设坏人捕获了完整的 HTTP 请求,他可以从这 2 个信息中提取密码吗?

代码详情(如果需要):

private static Cipher getCipher(String key, int mode) throws Exception{
     byte[] rawKey = getRawKey(key.getBytes("UTF-8"));
     SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
     Key key2 = skeySpec;
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
     cipher.init(mode, key2);
     return cipher;
}

private static byte[] getRawKey(byte[] seed) throws Exception {
/*  BEFORE:
     KeyGenerator kgen = KeyGenerator.getInstance("AES");
     SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
     sr.setSeed(seed);
     kgen.init(128, sr); // 192 and 256 bits may not be available
     SecretKey skey = kgen.generateKey();
     byte[] raw = skey.getEncoded();
*/
     byte[] raw = MD5Util.getMD5HashRaw(seed);
     return raw;
}

(注意:我之所以使用密码的哈希是因为代码在平台之间兼容(客户端是Android设备),而注释版本不是)

更新#1

简答:

所呈现的逻辑甚至不能被视为一种安全的身份验证机制 (为什么?在下面查看迈克尔的答案)

决定使用 Kerberos(而不是 https,因为我不熟悉 + 似乎设置起来很复杂):

它不是真正的 Kerberos 版本(如 v4 或 v5),它只是我自己的实现,所以我们称之为“与 Kerberos 类似”(我知道,我知道:不要“滚动你自己的加密”!!! ),

这里有一些细节:

  • 它适用于 UDP(现在)
  • 身份验证只进行一次,由:

    • 客户端发送 Authenticator 消息(包含:[userId] 纯文本和 [something_ecrypted] 和 [entered_user_password](目前 [something_ecrypted] 仅包含时间戳,称之为 [authenticator_creation_timestamp]))注意 : 密码不传输
    • 服务器收到消息后,尝试使用 [actual_user_password] 解密 [something_ecrypted] -> 如果成功,则客户端就是它假装的那个人,所以我给他发回一个 OK 响应(如在 Kerberos 中,此响应包含一些内容,就像一个 [public_key](一个 RSA 密钥,但使用 user_password 加密)+票证授予票证(称之为 [TGT],使用只有服务器知道的密码加密,目前它不会过期,这个 [TGT] 还包含一些东西,比如这 2 个时间戳:[TGT_creation_time_stamp] + [authenticator_creation_timestamp](在 Authenticator 消息中收到的那个))
    • 在收到此 OK 消息后,客户已经获得了一个有效的 [public_key].. 太好了!
  • 防止“回复攻击”不是 100% 的保证,但我认为它“足够安全”:

    • 在每个下一个 HTTP 请求中,我将这 2 个家伙 [new_request_creation_timestamp](使用 [public_key] 加密,上面采购的)+ [TGT](未触及,如上所述)作为标题附加
    • 在服务器上,我只需要验证 [new_request_creation_timestamp] 和一些数学(显然 [TGT] 也需要有效):

      ** 我希望以下变量几乎相等

      delta1 = [TGT_creation_time_stamp] - [authenticator_creation_timestamp]

      delta2 = now()-[new_request_creation_timestamp]

      (我实际上允许它们之间有 5 秒的差异,但从我的测试来看,它只是大约 10-20 毫秒,

      ** 所以初始增量(在创建对 Authenticator 的 OK 响应时计算)应该在下一次交互中持续存在。

我确实觉得这种新方法非常值得信赖,但是如果您有意见或发现逻辑上的 BUG,请分享.. 谢谢

【问题讨论】:

  • 这个方案的问题是,如果可以用加密后的用户名代替密码,那么基本上就是密码了。您通过未加密、未验证的连接发送它。您必须使用 HTTPS 才能使此方案起作用。请参阅迈克尔的回答。
  • 不要使用 SecureRandom#setSeed() 来派生密钥。见stackoverflow.com/questions/13433529/…

标签: java android security aes md5


【解决方案1】:

是的,这是一个弱安全机制。

  1. 捕获发送到服务器的信息的任何人都可以轻松地重放它以验证自己的身份(重放攻击)。

  2. 它很容易受到离线密码猜测 - 任何捕获发送到服务器的信息的人都可以非常快速地测试密码列表以找到您的用户选择的密码(通过使用每个密码的哈希加密观察到的用户名依次输入密码)。哈希甚至可以预先计算,进一步加快攻击速度。

基于密码的身份验证协议应该能够抵抗重放攻击和离线密码猜测攻击。

简单地使用 HTTPS (TLS) 连接到您的服务器并以明文形式发送用户名和密码通常是更好的解决方案。

响应您的更新 1:

  • 我强烈建议使用 HTTPS。它在任何地方都被使用是有原因的 - 它已经过大量的安全审查,并且被发现是(很大程度上)安全的 - 比您通过 SO 帖子所能获得的要好得多。
  • 我没有彻底考虑过您的更新方案,但由于它基于 Kerberos,因此也受到如上所述的离线密码猜测攻击。
  • 成功通过身份验证后,不要忘记实际保护您的数据 - 您可能需要派生一个共享对称密钥,然后对您的数据使用身份验证 + 加密...

【讨论】:

    【解决方案2】:

    我的理解是:您正在向服务器发送Username + Encrypted Username

    回答: 由于您发送的是Usernameencrypted Username,即:UserName + AES(UserName + MD5 Hashed Password)

    如果有人知道或发现您提供了用户名,并且还从您的数据中获取了用户名到服务器:No worries。你和AES站在一起。如果您对 AES 加密有疑问,请检查 this。您的数据是安全的。

    【讨论】:

    • 我不是密码学专家,但他肯定应该使用 SHA-256(或其他“更现代”的算法)而不是 MD5?
    • 看他问题的最后一行..,他用的是跨平台兼容性
    • 哪个平台没有SHA-256?
    • 鉴于 MD5 散列的长度,暴力攻击来反转加密是相当困难的,但是,鉴于已知的目标值(用户名),它可以完全自动化。一旦未加盐的散列被揭示,您可以使用许多预先计算的彩虹表中的任何一个来反转 MD5 散列。然而,它非常容易受到字典攻击。它也不能确保正确的身份验证,因为连接不安全。请参阅迈克尔的回答。
    • 有几种已知的对 MD5 的攻击。在 1.6GHz Pentium 上 8 小时内产生了碰撞。 [cryptography.hyperlink.cz/md5/MD5_collisions.pdf]。如果兼容性和速度不受限制,则没有理由在安全关键系统中使用 MD5。其他散列函数可能不是一个改进(由于 AES 可能无关紧要),但你为什么要故意使用最糟糕的选择?
    【解决方案3】:

    我不认为这本身就是一个安全漏洞,因为即使知道明文消息和加密消息,实际上也无法获得 AES 密钥。但我仍然不建议存储使用 MD5 散列的密码。

    【讨论】:

    • 如果你不听这个建议,你至少应该给它们加盐。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 2021-08-19
    相关资源
    最近更新 更多