我正在尝试将一个老的TLS 1.0实现(不是我编写的)更新以支持TLS 1.2。
作为第一步,我集成了TLS 1.1中的更改,将明文初始化向量放入记录。没有问题,看起来工作正常,我可以在TLS 1.1下读取https://example.com
以及SSL Labs viewMyClient.html。
然后我适应了TLS 1.2中的伪随机函数更改,使用(对于大多数实际目的)P_SHA256代替(更复杂和奇怪的)半MD5 / SHA1混杂。第一次做错了,得到了一个无效的MAC错误,但这基本上是我的一个打字错误,我修复了它。然后无效的MAC错误就消失了。
但是尽管如此,在发送ClientKeyExchange->ChangeCipherSpec消息之后,我从服务器那里收到了一个“解密错误”的返回消息(无论我尝试什么,都是相同的Alert,https://google.com
或其他任何内容)。我了解到ChangeCipherSpec消息仅加密一个字节,将其放入具有填充和MAC等内容的消息中。
如果我随机调整MAC一个字节,它会再次抱怨无效的MAC。 令我困惑的是MAC本身作为GenericBlockCipher的一部分进行了加密:
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;
更新: 顺便说一下,我已经添加了一个Wireshark记录文件,记录了1.2版本的
https://example.com
失败读取情况,以及一个运行相同代码(不包括P_SHA256 MAC更新)的成功的1.1版本会话的日志:http://hostilefork.com/media/shared/stackoverflow/example-com-tls-1.2.pcapng (失败) http://hostilefork.com/media/shared/stackoverflow/example-com-tls-1.1.pcapng (成功)
那么,到底是什么导致了解密出现问题呢?填充似乎是正确的,如果对字节进行加减1操作,就会收到无效MAC错误提示。(规范中指出,“接收方必须检查这个填充,并使用bad_record_mac警报来指示填充错误”,因此这是可以预料到的。)如果我在从加密过程中使用的消息中损坏了客户端iv(只需将传输版本中的一个错误的字节放入即可),这样做也会导致Bad Record MAC。我预计这也将破坏解密过程。
因此,我对问题感到困惑:
- 服务器演示了对有效MAC和无效MAC的区分,因此它必须解密成功。 它如何获得正确的MAC并出现解密错误?
- 密码套件是一个旧版本(TLS_RSA_WITH_AES_256_CBC_SHA),但我只是逐步解决一个问题......如果我没有弄错,这不应该有影响。
有没有经验丰富的人有关于TLS 1.2如何使本来在TLS 1.1中工作的代码失败的理论? (也许是那些已经对代码库进行过类似更新并不得不更改更多而不仅仅是我所做的两个事情的人?) 我是否忽略了其他重要的技术变化?我有什么方法可以找出是什么让服务器不开心?
CBC
模式下,不正确的IV
仅导致第1个块的解密错误。虽然奇怪的是它在1.1版本中能够工作但在1.2中不能,但没有调试信息,我只能想到这2个问题。 - Afshin