当前位置: 首页 > 知识库问答 >
问题:

TLS 1.2更改-密码-规范的"解密错误",但正确读取MAC

东方俊明
2023-03-14

我试图将旧的TLS 1.0实现(我没有写)更新为TLS 1.2。

作为第一步,我集成了TLS1.1更改,将明文初始化向量放入记录中。那没问题。它似乎工作得很好,我可以阅读https://example.com在TLS 1.1以及SSL Labs viewMyClient中。html。

然后,我适应了TLS1.2对伪随机函数的更改,将其改为(出于最实际的目的)P_SHA256,而不是(更复杂和奇怪的)一半和一半MD5/SHA1 rigamarole。我第一次做错了,得到了一个无效的MAC错误,但这或多或少是我的错别字,我修正了它。然后无效的MAC错误消失了。

尽管如此,在发送ClientKeyExchange之后-

如果我将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;

更新:FWIW,我添加了一个Wireshark日志,记录了1.2读取失败的情况https://example.com,以及运行相同代码的正常运行的1.1会话的日志,不包括P_SHA256 MAC更新:

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(只是在传输的版本中放入一个坏字节),那么这样做也会给我坏记录MAC。我希望这也会破坏解密。

所以我很困惑到底是什么问题:

  • 服务器显示了对有效MAC和无效MAC的区分,因此它必须已解密。它是如何得到正确的MAC和解密错误
  • 密码套件是一个古老的套件(TLS_RSA_和_AES_256_CBC_SHA),但我只是一次解决一个问题。。。如果我没弄错的话,那也没关系

有相关经验的人是否知道TLS 1.2如何给TLS 1.1中的代码带来麻烦?(也许有人对代码库做了类似的更新,并且不得不改变我已经改变的两件事情才能让它工作?)我错过了另一个关键的技术变化吗?我有什么办法来找出是什么让服务器不开心?

共有2个答案

艾焕
2023-03-14

我能想到两种不同的情况会产生这个问题:

  1. 发送错误的IVIV仅影响CBC模式解密中的第一个块,因此如果您的内容超过16字节(AES块大小),MAC部分数据将正确解密
  2. 如果您使用的填充结构不正确,则解密时可能会出错(因为填充验证失败),但内容将正确解密
司徒啸
2023-03-14

实际上,ChangeCipherSpec消息没有任何问题。实际上,问题出在已完成的消息上。它抱怨消息中解密的verify_data,与预期的散列不匹配(尽管加密/解密本身是正确的)。

但Wireshark日志中令人困惑的是,Finished消息显示在同一个日志行中,但名称为“EncryptedHandshakeMessage”,这使它看起来像某种描述ChangeCipherSpec的标签或标签,但事实并非如此。那封信实际上根本没有加密。

  • TLS完成数据包重命名加密握手消息

从第二个链接:

实际上,您将看到未加密的客户机Hello、服务器Hello、证书、服务器密钥交换、证书请求、证书验证和客户机密钥交换消息。完成的握手消息是加密的,因为它发生在更改密码规范消息之后。

“希望有人有过将TLS 1.0或1.1更新为1.2的经验,并且可能会因为更改的不超过P_SHA256 MAC和版本号而遇到类似问题”

在RFC 5246的"TLS 1.1更改"部分中,他们只提到了需要更新MD5/SHA1组合的三个地方中的两个:

>

数字签名元素中的MD5/SHA-1组合已替换为单个哈希。签名元素现在包含一个字段,该字段显式指定所使用的哈希算法。

(注意:第二种方法适用于证书,如果您还没有进行证书检查,那么您现在还不会进行证书检查。)

在该部分中,他们没有提到的是MD5/SHA-1组合更改的第三位,这是在Finished消息的verify\u数据的种子中使用的散列。然而,这一点也是TLS 1.1的一个变化,在第7.4节的文件中详细描述了这一点。9:

"哈希表示握手消息的哈希。对于第5节中定义的PRF,散列必须是用作PRF基础的散列。任何定义不同PRF的密码套件也必须定义在完成计算中使用的哈希。"

对于一个正式的规范,他们对“用作PRF基础的哈希”有点模糊(是HMAC还是普通哈希?)但这是普通的散列。所以SHA256,除非密码套件的规格另有规定。

(还要注意,密码套件可以规定verify_data的长度超过12个字节,尽管规范中没有提到这样做。)

"我有什么办法来找出是什么让服务器不开心?"

YMMV。但我所做的只是将OpenSSL构建为一个静态调试库,并将其链接到一个简单的服务器。然后,我添加了断点和插装,以查看它对什么感到不安。(出于某种原因,GDB不允许我进入共享库。)

大约30-Sep-2018,在一个普通的linux机器上:

  • git://git.openssl.org/openssl.git

我使用的简单服务器来自简单TLS服务器。根据静态库编译,使用:

  • gcc-g-O0简单。c-o simple-lssl-lcrypto-ldl-lpthread

我按照此处生成证书的说明操作,但将AAs更改为localhost

openSSL使用CA签署https_客户端证书

然后我更改了cert.pem=

wget https://localhost:4433 --no-check-certificate

并成功返回test作为响应。因此,接下来的问题只是看看我的客户在哪里导致了失败。

 类似资料:
  • 我试图更新一个旧的TLS1.0实现(我没有编写)来使用TLS1.2。 作为第一步,我集成了TLS1.1的更改,将明文初始化向量放在记录中。那没问题。它似乎工作得很好,我可以阅读TLS1.1中的,以及SSL实验室的viewmyclient.html。 然后,我将伪随机函数的TLS1.2修改为(出于最实际的目的)P_SHA256而不是(更复杂和奇怪的)半半MD5/SHA1 Rigamarole。我第一

  • 我已经试过这个,这个和这个,但我的问题解决不了。我不明白我做错了什么。下面是我的签名配置 这是当我试图运行应用程序时显示的错误 想不出该怎么办。提前感谢你的帮助。

  • 我正在尝试解密服务器上的加密字符串。但当我解密的时候,我发现了错误。我需要成功解密字符串。我们正在使用AES 256 cbc 当我使用aes/cbc/nopadding时,我能够解密,但是文本中附加了垃圾字符。 解密A:2:{S:5:“电子邮件”;S:24:“afroj.alam@broc.com”;S:8:“密码”;S:7:“test123”;} 实际字符串A:2:{S:5:“email”;S:

  • 问题内容: 节点无法创建用于SSL通信的安全上下文。 具体来说,我正在尝试让远程通知在iOS上运行。我使用了一个名为node-apn的模块,该模块引发以下错误: 不过,这似乎是一个通用错误,并且与APN并没有真正的关系。 问题答案: 这是因为您在生成证书时指定了密码。该密码必须由任何想要使用的人提供。 将通行短语字段添加到凭据即可解决此问题。

  • 问题内容: 我有一个主键为varchar(255)的表。在某些情况下,255个字符不够用。我尝试将字段更改为文本,但是出现以下错误: 我怎样才能解决这个问题? 编辑:我还应该指出,该表具有包含多个列的复合主键。 问题答案: 发生错误是因为MySQL只能索引BLOB或列的前N个字符。所以错误主要发生时,有一个领域/列类型或BLOB或那些属于或类型,如,,,,,和您尝试使一个主键或索引。无论长度是完整

  • 问题内容: 我目前有一个密钥库,其中只有我应该知道的特定密码。现在,我需要将对该密钥库的访问权授予其他人,因此我想: 1)更改密码,以便我可以与他人共享该密码并让他们签名 2)创建一个不同的密码并允许他们使用它进行签名。 这可能吗?以及-如果是-怎么样? 问题答案: 密钥库只有一个密码。您可以使用keytool进行更改: 要更改密钥的密码: