OpenSSL,公钥和私钥

3

我最近在使用C语言中的OpenSSL API进行实验,但是我对一些设置函数和公钥加密技术的概念感到困惑。

通常情况下,我了解公钥加密的工作原理。你有一个公钥可供所有人使用,服务器和客户端都拥有一个私钥,私钥是秘密的,必须用它来解密信息。

然而,我有点困惑于何时实际上需要公钥。例如,一个网页浏览器是否需要公钥?我认为不需要,因为在大多数情况下,只有服务器需要公钥而不是客户端。如果服务器和客户端都有公钥,那么哪个会被使用呢?

更让我困惑的是,OpenSSL API定义了一个函数SSL_CTX_use_PrivateKey_file(),但是没有相应的SSL_CTX_use_PublicKey_file()。在我的实验中,我编写了一个简单的Web客户端,连接到https网站并下载文件。它正常运行,并且不需要公钥。我只需使用OpenSSL命令行工具创建私钥,然后在程序中调用SSL_CTX_use_PrivateKey_file()

但是,如果我编写的是一个服务器而不是客户端,我不需要公钥吗?如果需要,为什么OpenSSL API中没有类似于use_PublicKey_file的东西呢?

4个回答

1
在TLS/SSL连接中,公钥作为证书的一部分被提供用于验证其中一个方的身份——证书将身份绑定到特定的公钥上。服务器始终提供证书(公钥),因为服务器必须始终向客户端证明自己的身份。
如果客户端想要证明其身份(并且具有合适的证书),也可以提供证书——在您的Web浏览器示例中,客户端通常不提供客户端证书,但是这是可能的。某些网站确实使用客户端证书进行身份验证。
如果使用公钥,则必须使用相应的私钥——密钥成对出现。提供公钥的相应函数是SSL_CTX_use_certificate()——公钥是证书的一部分。没有另一个密钥是没有意义的——在您的客户端示例中,您完全可以省略对SSL_CTX_use_PrivateKey_file()的调用。

那么,如果客户端没有调用SSL_CTX_use_PrivateKey_file(),那么用于解密消息的私钥是什么?OpenSSL会为每个会话即时生成一个私钥吗? - Channel72
@Channel72:这取决于使用的密码规范。在没有客户端证书的典型RSA握手中,客户端根本不使用公钥-它生成一个随机的预主密钥并使用服务器的公钥加密它。然后从预主密钥派生出主密钥。(重要的是要意识到,公钥密码仅用于初始连接设置,以协商实际用于加密和验证发送到连接上的数据的对称密钥)。 - caf

0

一般来说,私钥用于解密,公钥用于加密和验证。

我对OpenSSL C接口不是很熟悉,但我的猜测是,您实际上没有使用从文件加载的密钥。您正在使用的下载例程会下载Web服务器的证书,根据已知的签名机构链验证其签名,然后协商TLS(共享密码)加密流。

换句话说,对于HTTPS,公钥加密仅用于您的计算机在流密码协商之前验证服务器的真实性。完成后,双方将拥有共享密钥,并且所有内容都使用常规加密进行加密。

TLS RFC中包含所有详细信息。


0

密钥成对出现——对于每个公钥,都有一个相应的私钥;对于每个私钥,都有一个相应的公钥。因此,谈论“私钥”或“公钥”并没有任何意义——相反,您需要指定您正在谈论哪个密钥。

在“常规”(非客户端身份验证)SSL连接中,有一个密钥对,即服务器的密钥对。服务器知道自己的私钥,而客户端需要知道服务器的公钥,通常以证书的形式提供,该证书由某些证书颁发机构的私钥签名。因此,当客户端首次连接到服务器时,服务器首先发送其公钥证书(以便客户端获得它)。客户端使用CA的公钥对证书进行认证(该公钥需要内置或预载入)。然后客户端创建一个“秘密”(随机数),并使用服务器的公钥对其进行加密,然后将其发送到可以使用其私钥解密的服务器。然后,该“秘密”用于生成用于进一步通信的对称密码的密钥。

在经过身份验证的SSL连接中,客户端和服务器都拥有私钥,并在建立安全连接之前通过连接提供其证书(具有相应的公钥)。


只有RSA密码套件才适用于使用公钥加密秘密的部分。 - user207421
@EJP:它适用于任何使用密钥交换而不是Diffie-Hellman密钥生成的身份验证,无论密码套件如何。 DH略微复杂(基本上,双方都创建一个随机秘密,进行单向加密并发送,并与对方发送的内容相结合以创建对称密码密钥),但从根本上讲是相同的(创建用于加密流量的随机对称会话密钥)。 - Chris Dodd

-1

客户端通常不需要公钥。客户端在握手期间生成一个随机的公钥,以便服务器可以加密只有客户端才能解密的消息,但是此公钥的生命周期与连接的生命周期相同。

作为客户端,为了获取服务器的公钥,您将使用证书SSL_CTX_use_certificate_file。证书包含公钥,并且通常由受信任的证书颁发机构进行验证。只要您信任证书颁发机构,这就为客户端保证了服务器的真实性。Web浏览器附带一组受信任的证书颁发机构,因此它们可以验证它们将下载的证书。


实际上,由SSL_CTX_use_certificate_file加载的证书文件包含受信任证书颁发机构的CA证书,这些证书将用于验证客户端在初始连接设置协商过程中从服务器接收到的服务器证书。 - Chris Dodd
@Chris Dodd:不,Benoit是正确的——SSL_CTX_use_certificate_file()函数加载要提供给对等方的证书。SSL_CTX_load_verify_locations()函数用于加载CA证书以进行验证。 - caf
双方将独立协商使用的单个对称密钥,它不是公钥。 - user207421

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