AES加密&安全漏洞

时间:2013-12-02 09:45:24

标签: java android security aes md5

检查更新#1

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

  • 我正在发送:userName + encrypted_userName(encrypted_userName实际上是userName的加密结果,使用AES& amp;使用密码的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](curently [something_ecrypted]只包含一个时间戳,称之为[authenticator_creation_timestamp]))注意:密码未传输
    • 服务器收到消息后,尝试使用[actual_user_password]解密[something_ecrypted] - >如果SUCCESS然后客户端是它假装的人,那么我发送给他一个OK响应(如在Kerberos中这个响应包含一些东西,如[public_key](一个RSA密钥,但用user_password加密)+票证授予票证(呼叫)它[TGT],用服务器只知道的密码加密,目前它确实过期,这个[TGT]也包含一些东西,比如这2个时间戳:[TGT_creation_time_stamp] + [authenticator_creation_timestamp](在Authenticator消息中收到的那个))
    • 收到此确认消息后,客户端已经获得了有效的[public_key] ..太好了!
  • 再次保护“回复攻击”并非100%保证,但我认为这是“安全的”:

    • 在每次下一次HTTP请求时,我作为标题附加这两个人[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,请分享..谢谢

3 个答案:

答案 0 :(得分:3)

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

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

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

  3. 基于密码的身份验证协议应该能够抵御重放攻击和脱机密码猜测攻击。

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

    响应您的更新1:

    • 我强烈建议您使用HTTPS。它在任何地方都被使用是有原因的 - 它经过了大量的安全审查,并被发现(大部分)安全 - 远远超过你通过SO帖子得到的。
    • 我没有彻底考虑您的更新方案,但因为它基于Kerberos,它也会受到我上面描述的脱机密码猜测攻击。
    • 成功通过身份验证后,请不要忘记实际保护您的数据 - 您可能需要派生共享对称密钥,然后对数据使用身份验证+加密...

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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