Ssl &引用;“解密错误”;更改TLS 1.2的密码规范,但正确读取MAC
我正在尝试将一个旧的TLS1.0实现(我没有编写)更新到最新版本,以使用TLS1.2 作为第一步,我整合了TLS 1.1的变更。那没问题。它似乎工作得很好,我可以阅读Ssl &引用;“解密错误”;更改TLS 1.2的密码规范,但正确读取MAC,ssl,encryption,tls1.2,Ssl,Encryption,Tls1.2,我正在尝试将一个旧的TLS1.0实现(我没有编写)更新到最新版本,以使用TLS1.2 作为第一步,我整合了TLS 1.1的变更。那没问题。它似乎工作得很好,我可以阅读https://example.com在TLS 1.1以及SSL实验室中 然后,我适应了TLS1.2对伪随机函数的更改(出于最实际的目的)而不是(更复杂和奇怪)。我第一次做错了,得到了一个无效的MAC错误,但这或多或少是我的错别字,我修正了它。然后无效的MAC错误消失了 但尽管如此,在发送ClientKeyExchange->Cha
https://example.com
在TLS 1.1以及SSL实验室中
然后,我适应了TLS1.2对伪随机函数的更改(出于最实际的目的)而不是(更复杂和奇怪)。我第一次做错了,得到了一个无效的MAC错误,但这或多或少是我的错别字,我修正了它。然后无效的MAC错误消失了
但尽管如此,在发送ClientKeyExchange->ChangeCipherSpec消息后,我从服务器返回了一个“解密错误”(不管是什么警报,https://google.com
或我尝试过的任何东西)。我收集到ChangeCipherSpec消息只加密了一个字节,将其放入带有填充和MAC等的消息中
如果我将MAC随机调整一个字节,它就会返回到抱怨无效的MAC让我困惑的是:
struct {
opaque IV[SecurityParameters.record_iv_length];
block-ciphered struct {
opaque content[TLSCompressed.length];
opaque MAC[SecurityParameters.mac_length]; // <-- server reads this fine!
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;
};
} GenericBlockCipher;
struct{
不透明IV[安全参数.记录IV长度];
块加密结构{
不透明内容[TLSCompressed.length];
不透明MAC[SecurityParameters.MAC_length];//我可以想到造成此问题的两种不同情况:
发送不正确的IV
IV
只会影响CBC
模式解密中的第一个块,因此如果您的内容超过16字节(AES
块大小),MAC
部分数据将被正确解密
如果您使用的填充结构不正确,则解密时可能会出错(因为填充验证失败),但内容将正确解密
实际上,ChangeCipherSpec
消息没有任何问题。问题出在消息中。它抱怨消息中解密的verify\u数据
,与预期的哈希不匹配(尽管加密/解密本身是正确的)
但Wireshark日志中令人困惑的是,Finished
消息显示在同一个日志行中,但名称为“EncryptedHandshakeMessage
”,这使它看起来像某种描述ChangeCipherSpec的标签或标签,但它不是。该消息实际上根本没有加密
从第二个链接:
实际上,您将看到未加密的客户端Hello、服务器Hello、证书、服务器密钥交换、证书请求、证书验证和客户端密钥交换消息。完成的握手消息是加密的,因为它发生在更改密码规范消息之后
“希望有人有过将TLS 1.0或1.1升级到1.2的经验,并且可能会遇到类似的问题,原因是更改的版本不超过p_SHA256 MAC,并且版本号不一致”
它们只提到了在RFC 5246中更新MD5/SHA1组合所需的三个位置中的两个:
- 伪随机函数(PRF)中的MD5/SHA-1组合已替换为密码套件指定的PRF。本文档中的所有密码套件均使用p_SHA256
- 数字签名元素中的MD5/SHA-1组合已替换为单个哈希。签名元素现在包含一个字段,该字段显式指定所使用的哈希算法
(注意:第二种方法适用于证书,如果您还没有进行证书检查,那么您现在还不会进行证书检查。)
在该部分中,他们没有提到的是第三个位置MD5/SHA-1组合更改,这是一个散列,用于Finished
消息的verify_data
的种子。但是,这一点也是对TLS 1.1的更改,在以下文档中详细描述:
哈希表示握手消息的哈希。对于第5节中定义的PRF,哈希必须是用作PRF基础的哈希。任何定义不同PRF的密码套件也必须定义要在完成的计算中使用的哈希
对于一个正式的规范,他们在“作为PRF基础的散列”(是HMAC还是普通散列?)上有点含糊不清,但它是普通散列。所以SHA256,除非密码套件的规范另有规定
(请注意,密码套件可以规定验证_数据的长度超过12个字节,尽管规范中没有提到这样做。)
“我有什么办法来找出服务器不满意的原因?”
但我所做的只是将OpenSSL构建为一个静态调试库,并将其链接到一个简单的服务器。然后我添加了断点和插装,以查看它对什么感到不安。()
大约2018年9月30日,在普通linux机器上:
git://git.openssl.org/openssl.git
/config no shared no asm-g3-O0-fno省略帧指针-fno内联函数no-ssl2 no-ssl3
make
我使用的简单服务器来自。根据静态库编译,使用:
gcc-g-O0 simple.c-o simple-lssl-lcrypto-ldl-lpthread
我按照此处生成证书的说明操作,但将AAs更改为localhost
然后,我更改了简单服务器代码中的cert.pem=>rootCA.pem
和key.pem=>rootCA.key
。我能够做到:
wget https://localhost:4433 --no-check-certificate
并成功返回test
作为响应。因此,接下来的问题只是看看我的客户端在哪里导致了故障。Hm…只是猜测,但您使用的填充类型是否正确?如果您使用的填充不正确,则解密时会出错,但解密的数据是正确的。您的MAC将进行验证,但解密会产生错误