【问题标题】:SSL Client Certificate authenticationSSL 客户端证书认证
【发布时间】:2013-08-04 21:06:40
【问题描述】:
是否可以制作一个仅使用公钥和私钥进行客户端证书身份验证的程序(我没有生成任何证书,我只有公钥和私钥)。
很简单,
我想通过客户端证书认证在服务器上进行认证。
但是很难以编程方式制作客户端证书。
我想只使用公钥和私钥进行客户端证书身份验证(我只有公钥和私钥,没有证书)。
是否可以发送服务器公钥而不是客户端证书进行客户端证书认证?
【问题讨论】:
标签:
ssl
public-key-encryption
client-certificates
【解决方案1】:
TLS 协议只允许交换证书,不允许交换原始公钥。甚至“PGP 密钥”(如果您想用 OpenPGP for authentication in TLS 替换 X.509,它的支持要少得多)实际上也是证书(它们是公钥和一组标识符和属性的签名组合)。
话虽如此,您可以使用自签名客户端证书执行客户端身份验证并依赖其公钥(但您需要根据您的服务器已经知道的内容验证此公钥,例如已知列表)。您首先需要了解实现此功能的安全隐患。这与自签名服务器证书不是完全相同的问题。 (我建议保留更传统的方法来验证服务器证书。)
您可以让客户端发送自签名证书(可能使用certain tricks regarding the CA list advertised by the server)并在 TLS 堆栈中或稍后在应用程序中执行验证。
请注意,许多应用程序容器(例如 Java 中的 Tomcat/Jetty)期望 SSL/TLS 层来验证客户端证书。因此,如果您跳过那里的身份验证(并希望稍后在容器内或作为应用程序的一部分进行),许多应用程序框架将会混淆。在您的应用程序中执行任何需要身份验证的操作之前,您需要非常小心地确保在某处实际执行了身份验证。
例如,可以在 Tomcat/Jetty 中拥有一个允许任何客户端证书通过的信任管理器,但您不能依赖 javax.servlet.request.X509Certificate 请求属性以任何方式进行验证(大多数框架否则会期望)。您需要在应用程序中实现一些验证逻辑:例如,在任何经过身份验证的功能之前有一个过滤器,该过滤器将此客户端证书中的公钥与您已知的公钥列表进行比较(或者您希望将公钥与标识符)。或者,您也可以在自定义信任管理器中执行此验证(使用 Java),这将需要在应用程序中进行较少的工作。
您可以在 Apache Httpd + PHP 设置中执行类似的操作(例如),使用 SSLVerifyClient optional_no_ca。同样,您的 PHP 应用程序不能依赖已验证的证书,因此您也必须在那里实现验证。
除非您了解您获得的证书信息在哪个阶段得到验证,否则请勿执行任何此类操作。
【解决方案2】:
是否可以发送服务器公钥而不是客户端证书进行客户端证书身份验证?
没有。 SSL 协议已经定义。如果有可能,它就不会实现目标。服务器的公钥不会以任何形式或形式验证服务器的身份。