困惑如何客户端和服务器使用AES和Hmac将互相验证
情况是这样的:我有一个客户端和服务器通话。这里是标准的想法:困惑如何客户端和服务器使用AES和Hmac将互相验证
- 使用Diffie-Hellman在客户端和服务器之间生成一个密钥。
- 将此密钥用于客户端和服务器上的AES/CTR/PKCS7Padding密码。在原始消息
- 加密的HMAC消息AES加密
我看相关的代码示例是这里的教程:Tampered message with HMac, encryption with AES in CTR mode : Advanced Encryption Standard « Security « Java Tutorial
我能够生成客户端和服务器的密钥。我可以使用Hmac和AES对此进行加密。由于加密和解密独立发生,我不确定如何检索解密所需的相关信息。
这是我在困惑的部分:
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] plainText = cipher.doFinal(cipherText, 0, ctLength);
int messageLength = plainText.length - hMac.getMacLength();
hMac.init(hMacKey);
hMac.update(plainText, 0, messageLength);
byte[] messageHash = new byte[hMac.getMacLength()];
如果客户端发送的加密消息,请问服务器检索ivSpec
,hMac.getMacLength()
和hMacKey
?这些项目在服务器上需要解密来自客户端的消息。
我知道初始化向量(IV)可以从密文保留下来,因为它被附加到最终密文的开头(我想我不得不手动添加它,因为我不认为AES密码会那?)。然而,用于验证消息完整性的hMacKey和hMac长度仍然是一个谜。
在最后一个笔记上,有人可以解释这条线的目的是什么吗?这是加密还是解密?
cipherText[9] ^= '0'^'9';`
首先,对于这种类型的东西,如果你真的使用SSL。为了教育目的,这个东西很酷。
正如其他人所说,这是一个证明HMAC在密文被篡改时起作用的例子。因此,cipherText[9] ^= '0'^'9';
为了使用HMAC,您必须验证您使用密文获得的消息认证标记(由hmac返回的最新消息)是否与您应该拥有的消息认证标记匹配。要做到这一点在此代码:1)用你协商的密钥解密消息,2)使用你协商一个不同的密钥,然后3)计算该文本的HMAC比较,这两个是相同的。
由于您知道这些密钥,因此您可以解密消息并计算mac。 mac长度b是hmac函数的固定属性并且是公知的。
由于您必须具有生成有效标签的密钥,所以如果它们匹配,则该消息是可信的。
作为一个注释,这个代码可能是不安全的,因为你需要MAC密文,而不是明文。如果你不这样做,你最终会遇到像Padding oracle attack这样的问题,这些问题打破了一大堆网站安全cookie的实现。使用SSL来处理这些事情。
谢谢,我会实施你的建议。 – user1249144 2012-03-06 22:12:28
在这种情况下,hmac是明文还是密文?这个例子在密文中翻了一番,hmac发现了错误。那么在这里不需要使用密文? (这也只是为了学习,谢谢你的建议!)。 – user1249144 2012-03-07 20:11:37
是的,有很大的不同。如果明文,那么我可以将错误的数据提供给解密函数。例如,我可以更改填充数据。当你这样做时,大多数密码会返回并错误地说填充是错误的。我可以用它来读取消息。如果我使用密文,则不存在这样的问题。 – imichaelmiers 2012-04-27 17:15:03
你所看到的是这个例子的名称为“篡改......”。最后一行旨在向你展示当密文被篡改时会发生什么。如果你运行这个例子,Hmac应该会失败。 – 2012-03-05 12:15:47
啊,好的。这就说得通了。那么hMacKey或hMac长度呢?是否有可能使用相同的密钥重新生成相同的hMacKey? – user1249144 2012-03-05 16:51:26
只需使用SSL/TLS,您不必担心细节。此外,最好首先加密,然后进行身份验证,而不是反过来,以避免对密码进行选择性密文攻击。 – 2012-03-05 21:35:18