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

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

景宏富
2023-03-14

我试图更新一个旧的TLS1.0实现(我没有编写)来使用TLS1.2。

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

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

但是尽管如此,在发送了ClientKeyExchange->ChangeCipherSpec消息之后,我还是从服务器返回了一个“解密错误”(不管是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;

更新:FWIW,我添加了一个Wireshark日志,记录https://example.com失败的1.2读取,以及运行相同代码的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_WITH_AES_256_CBC_SHA),但我只是一次解决一个问题...如果我没有弄错的话,这应该无关紧要。

有相关经验的人有关于TLS1.2如何将扳手扔进TLS1.1中工作的代码的理论吗?(也许有人对代码库进行了类似的更新,并且必须更改比我更改的两件事情更多的东西才能让它工作?)我是不是错过了另一个关键的技术变化?我有什么追索权来找出是什么让服务器不高兴?

共有1个答案

壤驷喜
2023-03-14

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

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

  • TLS完成的数据包重命名为加密握手消息
  • TLS加密类型上的HTTPS

从第二个环节看:

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

希望有经验更新TLS 1.0或1.1到1.2的人,可能会看到类似的问题,因为没有改变更多的P_SHA256 MAC和颠簸版本号。

在RFC 5246的“从TLS 1.1进行的更改”一节中,它们只提到了更新MD5/SHA1组合所需的三个地方中的两个:

>

  • 伪随机函数(PRF)中的MD5/SHA-1组合已被密码套件指定的PRF所取代。本文档中的所有密码套件都使用P_SHA256。

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

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

    他们在这一节中没有提到的是MD5/SHA-1组合更改的第三个地方,这是在finished消息的verify_data种子中使用的散列。然而,这一点也是与TLS 1.1的一个变化,在7.4.9节中进一步描述了这一点:

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

    对于正式的规范,他们在“作为PRF基础的哈希”上有点含糊(是HMAC还是普通哈希?)但这是简单的哈希。所以SHA256,除非密码套件的规范另有规定。

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

    “我有什么办法来找出是什么让服务器不高兴?”

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

    大约在2018年9月30日,在一台普通的linux机器上:

    • git://git.openssl.org/openssl.git
    • ./config no-shared no-asm-g3-o0-fno-omit-frame-pointer-fno-inline-functions no-ssl2 no-SSL3
    • 制作

    我使用的简单服务器来自简单的TLS服务器。使用以下命令对静态库进行编译:

    • gcc-g-o0 simple.c-o simple-lssl-lcrypto-ldl-lpthread

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

    然后,我更改了简单服务器代码中的cert.pem=>rootca.pemkey.pem=>rootca.key。我能够做到:

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

    并成功地返回test作为响应。所以这只是一个问题,看看我的客户是在哪里导致了失败。

  •  类似资料:
    • 我试图将旧的TLS 1.0实现(我没有写)更新为TLS 1.2。 作为第一步,我集成了TLS1.1更改,将明文初始化向量放入记录中。那没问题。它似乎工作得很好,我可以阅读在TLS 1.1以及SSL Labs viewMyClient中。html。 然后,我适应了TLS1.2对伪随机函数的更改,将其改为(出于最实际的目的)P_SHA256,而不是(更复杂和奇怪的)一半和一半MD5/SHA1 riga

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

    • 我正在尝试解密服务器上的加密字符串。但当我解密的时候,我发现了错误。我需要成功解密字符串。我们正在使用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进行更改: 要更改密钥的密码: