- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个使用 C++ 编程语言的 OpenSSL 的 SSL/TLS 客户端程序。我正在寻找方法来验证 SSL_get_peer_certificate
函数调用返回的服务器证书 (X509
)。此外,我使用 SSL_CTX_load_verify_locations
函数加载了自己的 CA 证书。 CA认证了服务器证书。
我能够与我的服务器建立 SSL session 。现在,我想使用我自己的 CA 验证在 SSL 握手期间收到的服务器证书。我找不到用 C 或 C++ 执行此操作的方法。
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#define DEFAULT_PORT_NUMBER 443
int create_socket(char *, uint16_t port_num);
int openSSL_client_init()
{
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
SSL_load_error_strings();
if (SSL_library_init() < 0)
return -1;
return 0;
}
int openSSL_create_client_ctx(SSL_CTX **ctx)
{
const SSL_METHOD *method = SSLv23_client_method();
if ((*ctx = SSL_CTX_new(method)) == NULL)
return -1;
//SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2);
return 0;
}
int main(int argc, char *argv[])
{
BIO *outbio = NULL;
X509 *cert;
X509_NAME *certname = NULL;
SSL_CTX *ctx;
SSL *ssl;
int server = 0;
int ret, i;
if (openSSL_client_init()) {
std :: cerr << "Could not initialize the OpenSSL library !" << std :: endl;
return -1;
}
outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
if (openSSL_create_client_ctx(&ctx)) {
std :: cerr << "Unable to create a new SSL context structure." << std :: endl;
return -1;
}
std :: cout << "Adding Certifcate" << std :: endl;
if (SSL_CTX_load_verify_locations(ctx, "ca-cert.pem", NULL) <= 0) {
std :: cerr << "Unable to Load certificate" << std :: endl;
return -1;
}
ssl = SSL_new(ctx);
server = create_socket(argv[1], atoi(argv[2]));
if (server < 0) {
std :: cerr << "Error: Can't create TCP session" << std :: endl;
return -1;
}
std :: cout << "Successfully made the TCP connection to: " << argv[1] << " port: " << atoi(argv[2]) << std :: endl;
SSL_set_fd(ssl, server);
if (SSL_connect(ssl) != 1) {
std :: cerr << "Error: Could not build a SSL session to: " << argv[1] << std :: endl;
return -1;
}
std :: cout << "Successfully enabled SSL/TLS session to: " << argv[1] << std :: endl;
//SSL_SESSION *ss = SSL_get_session(ssl);
cert = SSL_get_peer_certificate(ssl);
if (cert == NULL) {
std :: cerr << "Error: Could not get a certificate from: " << argv[1] << std :: endl;
return -1;
}
certname = X509_NAME_new();
certname = X509_get_subject_name(cert);
std :: cout << "Displaying the certificate subject data:" << std :: endl;
X509_NAME_print_ex(outbio, certname, 0, 0);
std :: cout << std :: endl;
char msg[100000] = "GET / HTTP/1.1\r\nHOST: www.siliconbolt.com\r\n\r\n";
SSL_write(ssl, msg, strlen(msg));
SSL_read(ssl, msg, 100000);
std :: cout << "Message is " << msg << std :: endl;
SSL_free(ssl);
close(server);
X509_free(cert);
SSL_CTX_free(ctx);
std :: cout << "Finished SSL/TLS connection with server" << std :: endl;
return 0;
}
int create_socket(char *ip_cstr, uint16_t port_num)
{
int fd;
struct sockaddr_in dest_addr;
fd = socket(AF_INET, SOCK_STREAM, 0);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port_num);
dest_addr.sin_addr.s_addr = inet_addr(ip_cstr);
memset(&(dest_addr.sin_zero), '\0', 8);
if (connect(fd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1)
return -1;
return fd;
}
最佳答案
正确的证书验证是一件复杂的事情,而 OpenSSL 在这方面的帮助很小。如果您希望每个步骤都有完整的代码,我会认为这个问题太宽泛了。因此,我将专注于验证所需的基本部分,并主要指出其他资源以获取特定部分的实现细节。
验证服务器证书的第一步是建立到受信任的根 CA 证书的信任链。如果您设置了受信任的根(即在代码中调用 SSL_CTX_load_verify_locations
)并且还使用 SSL_CTX_set_verify 设置了验证模式,这将由 TLS 握手中的 openssl 隐式完成。到 SSL_VERIFY_PEER
。此内置验证还包括检查叶证书和链证书是否已经有效且尚未过期。
下一步是验证证书的主题是否与预期的匹配。对于服务器证书,这通常意味着目标主机名以某种方式包含在证书的通用名称或主题备用名称中。实际要求取决于应用层协议(protocol),即 HTTP、SMTP、LDAP ... 都有略微不同的规则,尤其是在涉及通配符的情况下。由于 OpenSSL 1.0.2 a a X509_check_host功能可用,在大多数情况下可用于检查规则。使用早期版本的 OpenSSL,您可以自己实现这样的功能。请注意,您明确需要验证主机名,即 OpenSSL 不会为您执行此操作,省略此步骤将使中间人攻击您的应用程序变得容易。
此时您知道证书是由受信任的根 CA 直接或间接颁发的,并且证书与预期的主机名匹配。您现在需要检查证书是否被吊销。一种方法是使用您在某处获得的证书撤销列表 (CRL),另一种方法是使用在线证书状态协议(protocol) (OCSP)。
对于 CRL,请参阅 Does OpenSSL automatically handle CRLs (Certificate Revocation Lists) now?如何使用您已经下载的 CRL。但是 OpenSSL 首先不会帮助您下载 CRL。相反,您需要从叶证书中提取 CRL 分发点,自行下载 CRL,然后才能使用。
至于 OCSP,OpenSSL 提供必要的 API 来构建 OCSP 请求和验证 OCSP 响应。您仍然需要自行确定将此 OCSP 请求发送到何处。这需要通过解析叶证书并从授权信息访问字段中提取 OCSP URL 来再次完成。虽然其余部分有 API,但它不容易使用,并且至少在 OpenSSL 1.1.0 版之前大部分或完全没有记录。我不知道使用此 API 实现 OCSP 验证的好且易于理解的示例,但您可以查看 openssl ocsp
命令和 its implementation .
如果您编写了一个客户端应用程序并且只想接受一个证书,您可以省略所有针对 PKI 进行验证的复杂步骤。但只检查证书是否完全符合预期,即证书固定。参见 OWASP: Certificate and Public Key Pinning有关这方面的更多信息和示例代码。
关于c++ - 用于验证 SSL_get_peer_certificate 返回的服务器证书的客户端程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40063533/
在 JSF2 应用程序中遇到验证属性的问题时,有两种主要方法。 使用 Annotation 在 ManagedBean 上定义验证 @ManagedBean public class MyBean {
我想实现一个不常见的功能,我认为 jquery 验证插件将是最好的方法(如果您在没有插件的情况下建议和回答,我们也会欢迎)。我想在用户在输入字段中输入正确的单词后立即隐藏表单。我试过这个: $("
我有几个下拉菜单(类名为month_dropdown),并且下拉菜单的数量不是恒定的。我怎样才能为它们实现 NotEqual 验证。我正在使用 jQuery 验证插件。 这就是我写的 - jQuery
我设法制作了这个网址验证代码并且它起作用了。但我面临着一个问题。我认为 stackoverflow 是获得解决方案的最佳场所。 function url_followers(){ var url=do
我目前正在使用后端服务,该服务允许用户在客户端应用程序上使用 Google Games 库登录。 用户可以通过他们的 gplay ID 向我们发送信息,以便登录或恢复旧帐户。用户向我们发送以下内容,包
我正在尝试验证输入以查看它是否是有效的 IP 地址(可能是部分地址)。 可接受的输入:172、172.112、172.112.113、172.112.113.114 Not Acceptable 输入
我从 Mongoose 验证中得到这条消息: 'Validator failed for path phone with value ``' 这不应该发生,因为不需要电话。 这是我的模型架构: var
我一直在尝试使用Python-LDAP (版本 2.4.19)在 MacOS X 10.9.5 和 Python 2.7.9 下 我想在调用 .start_tls_s() 后验证与给定 LDAP 服务
我正在处理一个仅与 IE6 兼容的旧 javascript 项目(抱歉...),我想仅在 VS 2017 中禁用此项目的 ESLint/CSLint/Javascript 验证/CSS 验证。 我知道
我正在寻找一种方法来验证 Spring 命令 bean 中的 java.lang.Double 字段的最大值和最小值(一个值必须位于给定的值范围之间),例如, public final class W
我正在尝试在 springfuse(JavaEE 6 + Spring Framework (针对 Jetty、Tomcat、JBoss 等)) 和 maven 的帮助下构建我的 webapps 工作
我试图在我们的项目中使用 scalaz 验证,但遇到了以下情况: def rate(username: String, params: Map[String, String]): Validation
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
我有一个表单,人们可以单击并向表单添加字段,并且我需要让它在单击时验证这些字段中的值。 假设我单击它两次并获取 2 个独立的字段集,我需要旋转 % 以确保它在保存时等于 100。 我已放入此函数以使其
在我的页面中有一个选项可以创建新的日期字段输入框。用户可以根据需要创建尽可能多的“截止日期”和“起始日期”框。就像, 日期_to1 || date_from1 日期到2 ||日期_from2 date
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
有没有办法在动态字段上使用 jquery 验证表单。 我想将其设置为必填字段 我正在使用 Jsp 动态创建表单字段。 喜欢 等等...... 我想使用必需的表单字段验证此表单字段。 最佳答
嗨,任何人都可以通过提供 JavaScript 代码来帮助我验证用户名文本框不应包含数字,它只能包含一个字符。 最佳答案 使用正则表达式: (\d)+ 如果找到匹配项,则字符串中就有一个数字。 关于J
我有两个输入字段holidayDate和Description(id=tags) $(document).ready(function() {
我遇到了这个问题,这些验证从电子邮件验证部分开始就停止工作。 我只是不明白为什么即使经过几天的观察,只是想知道是否有人可以在这里指出我的错误? Javascript部分: function valid
我是一名优秀的程序员,十分优秀!