“unknown ca”问题解决:使用自行生成的CA证书和客户端/服务器证书

8
我正在编写一个自定义的客户端和服务器,希望它们可以在公共互联网上安全通信,因此我想使用OpenSSL,并让双方进行对等验证,以确保我的客户端没有被中间人误导,同样地,未经授权的客户端也无法连接到服务器。
这是在 SSL_connect / SSL_accept 阶段从服务器收到的错误信息:
15620:error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:ssl\record\rec_layer_s3.c:1528:SSL alert number 48

我正在运行Windows 10操作系统,使用OpenSSL 1.1.1。以下是我用来创建它们的批处理文件。由于很明显,我手动输入CA私钥密码。

openssl genrsa -out -des3 ca.key.pem 2048
openssl genrsa -out server.key.pem 2048
openssl genrsa -out client.key.pem 2048

openssl req -x509 -new -nodes -key ca.key.pem -sha256 -days 365 -out ca.cert.pem -subj /C=US/ST=CA/L=Somewhere/O=Someone/CN=Foobar

openssl req -new -sha256 -key server.key.pem -subj /C=US/ST=CA/L=Somewhere/O=Someone/CN=Foobar -out server.csr
openssl x509 -req -in server.csr -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out server.cert.pem -days 365 -sha256

openssl req -new -sha256 -key client.key.pem -subj /C=US/ST=CA/L=Somewhere/O=Someone/CN=Foobar -out client.csr
openssl x509 -req -in client.csr -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -out client.cert.pem -days 365 -sha256

本意在于创建自签名的CA,然后让它直接签署客户端和服务器密钥。

ca.key.pem将存储在安全的地方:在加密的veracrypt卷中。

客户端和服务器都会使用以下调用来启用对等验证:

    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);

我相当确定这是一个证书问题,因为如果我删除那行代码,错误就会消失。

2个回答

17

我自己回答一下,这样可以帮助到其他可能会寻找解决方案的人。答案在另一个SO问题中被发现,但在此值得重复:CA的公共名称不能与客户端和服务器证书的公共名称相同。

因此,将批处理文件的第四行更改为:

openssl req -x509 -new -nodes -key ca.key.pem -sha256 -days 365 -out ca.cert.pem -subj /C=US/ST=CA/L=Somewhere/O=Someone/CN=FoobarCA

解决了这个问题。


2
谢天谢地,这是我疏忽了,但完全犯了同样的错误。 - Chavez

5
$ openssl req -x509 -new ... -addext basicConstraints=critical,CA:TRUE 

这本质上创建了一个具有两个基本约束CA:TRUE扩展的证书:

$ openssl x509 -in ca.cert.pem -text
    X509v3 extensions:
        ...
        X509v3 Basic Constraints: critical
            CA:TRUE
        X509v3 Basic Constraints: critical
            CA:TRUE

尝试使用CA验证服务器证书将不起作用:
$ openssl verify -CAfile ca.cert.pem server.cert.pem 
C = XX, ST = XX, L = XX, O = XX, CN = CA
error 24 at 1 depth lookup: invalid CA certificate
error server.cert.pem: verification failed

鉴于此简单检查无法工作,客户端也将无法验证服务器证书,导致出现“未知CA”警报:

...:tlsv1 alert unknown ca:...

如果省略-addext选项,则会创建一个自签名证书,该证书已经具有CA:TRUE属性,如文档所述。

$ openssl req -x509 -new ... 
...
$ openssl x509 -in ca.cert.pem -text
    X509v3 extensions:
        ...
        X509v3 Basic Constraints: critical
            CA:TRUE

使用此方法验证服务器证书:

$ openssl verify -CAfile ca.cert.pem server.cert.pem 
server.cert.pem: OK

这个证书还应该被您的客户成功验证,这样就不会再出现“未知CA”错误。


我已经编辑了问题以反映出现的情况,但服务器仍然生成“未知CA”错误。所以我还是有些问题。是否已经到了发布整个源代码而不是片段的时候了? - dgnuff
发现问题了,在这个SO问题上:https://dev59.com/KWIj5IYBdhLWcg3w95cc。我可能应该避免用“XX”替换`-subj`选项中的参数,但我这样做是因为我不想公开它们。话虽如此,我一直在为CA和两个密钥使用相同的`CN=`值,这显然是完全不可取的。 - dgnuff
@dgnuff:它需要通过主题或授权密钥标识符(你没有)找到发行者,因此除非主题和发行者相同,否则它不得具有相同的主题和发行者信息。 - Steffen Ullrich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接