Ruby openssl SSLContext 密码

Ruby openssl SSLContext cipher

我在 Ruby 中使用从 cloudflare.com 获取证书链的 OpenSSL 库编写了以下代码。但 Cloudflare 有一个混合系统,旧浏览器接收 RSA 证书,新客户端接收 ECDSA 证书(参见 https://www.ssllabs.com/ssltest/analyze.html?d=cloudflare.com&s=104.17.176.85)。 在我的例子中,我想获得旧的 RSA 证书,这就是我设置 ctx.ciphers = 'aRSA' 的原因。但不知何故,我总是收到 ECDSA 证书。 尽管以下命令有效 openssl s_client -cipher aRSA -connect cloudflare.com:443 -showcerts.

require 'openssl'

ctx = OpenSSL::SSL::SSLContext.new
ctx.ciphers = 'aRSA'
sock = Socket.tcp("https://www.cloudflare.com", 443, connect_timeout: 10)
connection = connect(sock, ctx, hostname)
connection.peer_cert_chain

def connect(sock, ctx, url)
   ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
   ssl.hostname = url
   begin
      ssl.connect_nonblock
   rescue IO::WaitReadable
      return nil unless IO.select([ssl], nil, nil, 10)

      retry
   rescue IO::WaitWritable
      return nil unless IO.select(nil, [ssl], nil, 10)

      retry
   end
   ssl
end

谢谢

Ruby版本:2.6.3 Ruby OpenSSL 版本:2.2.0 OpenSSL 版本:LibreSSL 2.8.3

TLS 1.3 改变了密码套件的定义方式。来自 OpenSSL Wiki:

The new ciphersuites are defined differently and do not specify the certificate type (e.g. RSA, DSA, ECDSA) or the key exchange mechanism (e.g. DHE or ECHDE). This has implications for ciphersuite configuration.

在您的情况下,即使您指定了 aRSA,OpenSSL 仍包含 1.3 密码,它将与 EC 证书一起使用。

我不知道是否可以指定密码列表来排除这些密码(我无法让它工作),但你可以简单地将最大版本设置为 1.2:

ctx.max_version = :TLS1_2
ctx.ciphers = 'aRSA'

这应该让 Cloudflare 使用 RSA 证书。

我认为在 TLS 1.3 中指定不需要 ECDSA 证书的正确方法是在请求中使用 signature_algorithms 扩展字段,但是 Ruby 的 OpenSSL 绑定不不支持。