深入解析HTTPS连接与SSL协议

5星 · 超过95%的资源 需积分: 16 72 下载量 76 浏览量 更新于2024-08-01 2 收藏 844KB DOCX 举报
“HTTPS连接 解析 SSL” HTTPS连接是一种安全的HTTP协议,用于在Web浏览器和服务器之间建立加密通信,确保数据传输的隐私和完整性。SSL(Secure Sockets Layer)最初由Netscape公司开发,但现在通常指的是与其非常相似的TLS(Transport Layer Security)协议,后者由IETF接手并进一步发展。 当用户通过HTTPS访问一个网站,如Amazon,浏览器首先发送一个“ClientHello”消息开始SSL/TLS握手过程。这个消息包含以下关键信息: 1. **版本信息**:ClientHello消息中包含了客户端支持的最高TLS版本,例如0x0301代表TLS 1.0(SSL 3.1)。 2. **随机数**:为了生成会话密钥,客户端会发送一个包含当前时间戳和随机数据的字段。这个随机数对于后续的密钥协商至关重要。 3. **会话标识符**:如果浏览器之前已经与服务器建立过安全连接,并且该会话仍然有效,客户端可以发送之前会话的标识符,以便快速恢复连接,跳过完整的握手过程,提高性能。 4. **加密套件列表**:客户端列出它支持的所有加密算法和哈希函数,包括对称加密、非对称加密、MAC算法等,供服务器选择。 5. **压缩方法**:客户端也可以提供可接受的压缩算法,尽管在现代TLS实现中,由于安全考虑,压缩通常被禁用。 服务器收到ClientHello后,回应一个“ServerHello”消息,选择双方都支持的最高版本、加密套件和会话标识(如果适用)。接着,服务器会发送其证书,用于验证服务器的身份。证书通常由受信任的证书颁发机构签名,包含服务器的公钥。 服务器还会发送“ServerKeyExchange”和“CertificateRequest”(如果需要客户端认证)消息,接着是一个“ServerHelloDone”消息,表示服务器的握手消息结束。 客户端验证服务器证书的有效性后,发送“ChangeCipherSpec”和“Finished”消息,表明后续的数据都将使用协商的密钥加密。服务器同样发送“ChangeCipherSpec”和“Finished”消息,确认密钥交换已完成。至此,握手过程结束,客户端和服务器开始使用加密的HTTP(HTTPS)通信。 在整个过程中,Wireshark这样的网络分析工具可以帮助我们深入了解这些复杂的交互细节,提供透明度,帮助开发者和安全专家理解并调试HTTPS连接的问题。 HTTPS通过SSL/TLS协议提供了加密、身份验证和完整性保护,是网上交易、敏感信息传输等场景的基础保障。理解这个过程对于网络安全和Web应用开发至关重要。

下面函数 第四个参数是什么意思, char *https_request(const char *url, const char *payload, const char *cert_path, const char *key_path, const char *ca_path) { SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); // 加载 CA 证书 X509_STORE *store = X509_STORE_new(); X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); X509_LOOKUP_load_file(lookup, ca_path, X509_FILETYPE_PEM); // 加载客户端证书和私钥 SSL_CTX *ctx = SSL_CTX_new(TLS_method()); if (ctx == NULL) { perror("SSL_CTX_new"); return ("A"); } // 设置支持的协议版本为 TLSv1.2 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); //SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_client_method()); SSL_CTX_use_certificate_file(ctx, cert_path, SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM); // 创建 SSL 连接 SSL *ssl = SSL_new(ctx); // 解析 URL char host[256]; char path[4096]; int port = 443; if (sscanf(url, "https://%255[^/]/%4095s", host, path) != 2) { fprintf(stderr, "Error: Invalid URL\n"); return NULL; } // 创建 TCP 连接 int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in dest_addr; dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(port); dest_addr.sin_addr.s_addr = inet_addr(host); // 建立连接 connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); // 将 SSL 连接和 TCP 连接关联 SSL_set_fd(ssl, sockfd); // 进行 SSL 握手 SSL_connect(ssl); // 发送 HTTPS 请求 char request[8192]; snprintf(request, sizeof(request), "POST %s HTTP/1.1\r\n" "Host: %s\r\n" "Content-Type: application/json\r\n" "Content-Length: %zu\r\n" "\r\n" "%s", path, host, strlen(payload), payload); SSL_write(ssl, request, strlen(request)); // 接收 HTTPS 响应 char buf[8192]; int bytes; size_t response_size = 0; char *response_buf = NULL; while ((bytes = SSL_read(ssl, buf, sizeof(buf))) > 0) { response_buf = realloc(response_buf, response_size + bytes + 1); memcpy(response_buf + response_size, buf, bytes); response_size += bytes; } response_buf[response_size] = '\0'; // 关闭 SSL 连接 SSL_shutdown(ssl); // 释放资源 SSL_free(ssl); close(sockfd); SSL_CTX_free(ctx); X509_STORE_free(store); ERR_free_strings(); return response_buf; }

2023-06-02 上传

下面的代码修改一下 需要支持https双向认证int https_post(const char *cert_path, const char *url, const char *body, char *response) { int sockfd, len; struct sockaddr_in dest; struct hostent *host; SSL_CTX *ctx; SSL ssl; char request[MAX_BUF_SIZE], buf[MAX_BUF_SIZE]; // 初始化OpenSSL库 SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); // 解析主机名 //printf("66666666 %s\n", url); char hostname[2560]; getHostFromURL(url, hostname); host = gethostbyname(hostname); if (host == NULL) { perror("gethostbyname"); return -1; } // 创建套接字 sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); return -1; } // 设置目标地址 bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; dest.sin_port = htons(443); dest.sin_addr.s_addr = (long)host->h_addr; // 连接服务器 if (connect(sockfd, (struct sockaddr)&dest, sizeof(dest)) != 0) { perror("connect"); return -1; } ctx = SSL_CTX_new(TLS_method()); // 设置支持的协议版本为 TLSv1.2 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); if (ctx == NULL) { perror("SSL_CTX_new"); return -1; } // 加载证书 if (SSL_CTX_load_verify_locations(ctx, cert_path, NULL) != 1) { perror("SSL_CTX_load_verify_locations"); return -1; } // 创建SSL ssl = SSL_new(ctx); if (ssl == NULL) { perror("SSL_new"); return -1; } // 将套接字绑定到SSL SSL_set_fd(ssl, sockfd); // SSL握手 if (SSL_connect(ssl) == -1) { perror("SSL_connect"); return -1; } // 构造HTTP请求 char *escaped_url = urlencode(url); sprintf(request, "POST / HTTP/1.1\r\n" "Host: %s\r\n" "Content-Type: application/json\r\n" "Content-Length: %d\r\n" "\r\n" "%s", escaped_url, strlen(body), body); // 发送HTTP请求 SSL_write(ssl, request, strlen(request)); // 接收HTTP响应 len = SSL_read(ssl, buf, MAX_BUF_SIZE); printf("response %s\n", buf); // 关闭SSL和套接字 SSL_free(ssl); close(sockfd); // 处理响应 strncpy(response, buf, len); printf("Child process created with PID %d\n", 60909); response[len] = '\0'; printf("Child process created with PID %d\n", 70909); // 清理OpenSSL库 SSL_CTX_free(ctx); EVP_cleanup(); printf("Child process created with PID %d\n", 909); free(escaped_url); return 0; }

2023-06-01 上传