【问题标题】:OpenSSL DH Key Too Small ErrorOpenSSL DH 密钥太小错误
【发布时间】:2020-06-25 21:23:44
【问题描述】:

我正在尝试使用简单的 PERL 脚本连接到封闭的服务器 - 空调

#!/usr/bin/perl

use 5.10.1;
use warnings;
use strict;
use IO::Socket::SSL;
use IO::Socket::SSL qw/debug3/;
my $sock = IO::Socket::SSL->new(
        PeerHost => '192.168.1.4',
        PeerPort => 2878,
        verify_hostname => 0,   
        SSL_verify_mode => SSL_VERIFY_NONE,
        SSL_verifycn_scheme => undef
) or die "failed connect or ssl handshake: $!,$SSL_ERROR";
print "$sock\n";

现在,这一切都运行良好,然后我更新了 OpenSSL (libssl1.0.0) 准确地说,一切都崩溃了:

DEBUG: .../IO/Socket/SSL.pm:220: set domain to 2
DEBUG: .../IO/Socket/SSL.pm:1653: new ctx 1984680
DEBUG: .../IO/Socket/SSL.pm:363: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:365: socket connected
DEBUG: .../IO/Socket/SSL.pm:383: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:446: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1328: SSL connect attempt failed with unknown error error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small

DEBUG: .../IO/Socket/SSL.pm:452: fatal SSL error: SSL connect attempt failed with unknown error error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small
DEBUG: .../IO/Socket/SSL.pm:1328: IO::Socket::INET6 configuration failed error:00000000:lib(0):func(0):reason(0)

DEBUG: .../IO/Socket/SSL.pm:1690: free ctx 1984680 open=1984680
DEBUG: .../IO/Socket/SSL.pm:1698: OK free ctx 1984680
failed connect or ssl handshake: ,IO::Socket::INET6 configuration failed error:00000000:lib(0):func(0):reason(0) at ./spare line 9.

我很乐意使用任何替代软件包来解决这个问题,但我确实需要解决它,因为我无法更新空调上的证书...

我曾考虑使用 LWP 和原始 Net:SSLeay,但问题似乎出在底层 OpenSSL 库中。

【问题讨论】:

  • 用于 SSL/TLS 的证书密钥多长时间?推荐值为 4096 或至少 2048。
  • 回声 | openssl s_client -connect 192.168.1.4:2878 2>/dev/null | openssl x509 -text -noout | grep "Public-Key" 公钥:(1024 位)

标签: perl ssl openssl


【解决方案1】:
... SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small

我曾考虑使用 LWP 和原始 Net:SSLeay,但问题似乎出在底层 OpenSSL 库中。

虽然它是由 OpenSSL 更改引起的,但问题实际上出在服务器端。服务器在密钥交换中使用弱 DH 密钥,并且由于 Logjam attack,最新版本的 OpenSSL 强制使用非弱 DH 密钥。

如果服务器支持不使用 DH 密钥交换的密码,您可以通过限制客户端提供的密码以使其不包含任何 DH 密码来解决此问题。

my $sock = IO::Socket::SSL->new(..., SSL_cipher_list => 'DEFAULT:!DH' ...);

除了像你这样简单地禁用任何验证是不好的:

    ...
    verify_hostname => 0,   
    SSL_verify_mode => SSL_VERIFY_NONE,
    SSL_verifycn_scheme => undef

一方面,verify_hostname 根本不是有效参数(这仅适用于 LWP)。此外,如果您使用 SSL_verify_mode 禁用验证,则无需设置 SSL_verifycn_scheme,因为没有验证也意味着没有验证证书主题。

但比禁用验证要好得多的是使用SSL_fingerprint 指定您期望的证书,因此即使对自签名或过期证书也有适当的检查。有关详细信息,请参阅 IO::Socket::SSL 文档中的 common usage errors

【讨论】:

  • 我知道忽略 SSL 错误是可怕的,可取之处在于它只是用于空调 - 证书甚至不需要在那里,因为这只是通过私人 in -房屋网络。不过感谢您的指点,我会尽快调查他们。
  • 将 SSL_cipher_list => 'DEFAULT:!DH' 添加到选项中效果很好。
【解决方案2】:

在我的情况下,唯一的解决方案是在 /etc/ssl/openssl.cnf 中设置 CipherString 来自

CipherString = DEFAULT@SECLEVEL=2

CipherString = DEFAULT@SECLEVEL=1

【讨论】:

  • 虽然可行,但最好在单独的文件openssl-weak.cnf 中进行更改,然后仅为遇到此问题的程序设置 OPENSSL_CONF 环境变量。跨度>
  • 我的 openssl.cnf 没有 CipherString 选项
猜你喜欢
  • 1970-01-01
  • 2020-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多