90行代码实现C语言版https服务器,基于openssl

为了实现C语言版的https服务器(ubuntu linux),我查了很多资料,最后发现是非常简单好写的,在此向大家做个分享。

首先大致了解一下https的工作原理,下面这张图解释得非常好。

 

而openssl又对上面这张图里的一些功能进行了合并封装,让我们用起来更加方便简洁。

首先我们需要安装openssl开发包:

apt install openssl libssl-dev

然后就可以编译下面的mini版https server了 (https.c)

/*
gcc https.c -lssl -lcrypto   -o https
*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define BufSize 30 * 1024

int create_socket_listen(int port)
{
  int s;
  struct sockaddr_in addr;

  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = htonl(INADDR_ANY);

  s = socket(AF_INET, SOCK_STREAM, 0);  if (s < 0) {   perror("Unable to create socket");  exit(EXIT_FAILURE);  }
  if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {  perror("Unable to bind");  exit(EXIT_FAILURE); }
  if (listen(s, 1) < 0) { perror("Unable to listen"); exit(EXIT_FAILURE);   }

  return s;
}


SSL_CTX* initSSL(const char* cert, const char* key)
{
  //todo 可能存在泄露
  SSL_CTX* ctx;


  /* SSL 库初始化 */
  SSL_library_init();
  /* 载入所有 SSL 算法 */
  OpenSSL_add_all_algorithms();
  /* 载入所有 SSL 错误消息 */
  SSL_load_error_strings();
  /* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text, 也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准 */
  ctx = SSL_CTX_new(SSLv23_server_method()); if (ctx == NULL) { ERR_print_errors_fp(stdout);  return NULL; }
  

  /* 载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */
  if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM) <= 0) {  ERR_print_errors_fp(stdout);  return NULL;  }
  /* 载入用户私钥 */
  if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) {   ERR_print_errors_fp(stdout);   return NULL;  }
  /* 检查用户私钥是否正确 */
  if (!SSL_CTX_check_private_key(ctx)) {  ERR_print_errors_fp(stdout);  return NULL; }


  return ctx;
}


int main(int argc, char** argv)
{
  int port = 5555;
  int sock;
  SSL_CTX* ctx;
  char buf[BufSize];

  /* Ignore broken pipe signals */
  signal(SIGPIPE, SIG_IGN);

  ctx = initSSL("./fullchain.pem", "./privkey.pem"); if (ctx == NULL) { return 0; }

  sock = create_socket_listen(port);

  /* Handle connections */
  while (1) 
  {
    struct sockaddr_in addr;
    unsigned int len = sizeof(addr);
    SSL* ssl;
    const char reply[] = "HTTP/1.1 200 OK\r\nDate: Fri, 22 May 2009 06:07:21 GMT\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n<html><head></head><body>hello world</body></html>";

    int client = accept(sock, (struct sockaddr*)&addr, &len);  if (client < 0) {  perror("Unable to accept"); exit(EXIT_FAILURE);  }

    ssl = SSL_new(ctx); SSL_set_fd(ssl, client);
    if (SSL_accept(ssl) <= 0) { ERR_print_errors_fp(stderr); goto end; }

    int size = SSL_read(ssl, buf, BufSize); printf("ssl_read(%d): \n%s\n", size, buf); 

    SSL_write(ssl, reply, strlen(reply));

  end:
    SSL_shutdown(ssl);  SSL_free(ssl);  close(client);
  }

  close(sock);
  SSL_CTX_free(ctx);
}

编译命令:

gcc https.c -lssl -lcrypto   -o https

运行前需要准备好证书fullchain.pem和私钥privkey.pem两个文件,运行:

./https

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
使用C语言实现HTTPS可以是一个复杂的任务。HTTPS是基于HTTP协议的安全本,它使用SSL/TLS协议进数据加密和身份验证。要在C语言实现HTTPS,您需要使用SSL/TLS库,例如OpenSSL或mbedTLS。 下面是一个使用OpenSSL库在C语言实现HTTPS的简单示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/ssl.h> #include <openssl/bio.h> #include <openssl/err.h> int main() { // 初始化OpenSSLSSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); // 创建SSL上下文 SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method()); // 创建套接字 int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 连接服务器 struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(443); inet_pton(AF_INET, "example.com", &(server_addr.sin_addr)); if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("Error connecting to server"); exit(1); } // 创建SSL对象并将其与套接字关联 SSL *ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); // 建立SSL连接 if (SSL_connect(ssl) <= 0) { ERR_print_errors_fp(stderr); exit(1); } // 发送HTTPS请求 const char *request = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"; SSL_write(ssl, request, strlen(request)); // 接收和打印响应 char response[4096]; memset(response, 0, sizeof(response)); SSL_read(ssl, response, sizeof(response) - 1); printf("%s\n", response); // 关闭SSL连接和套接字 SSL_shutdown(ssl); SSL_free(ssl); close(sockfd); // 清理 SSL_CTX_free(ctx); ERR_free_strings(); return 0; } ``` 请注意,此代码仅提供了一个基本的示例,并可能需要根据您的特定需求进进一步的修改和完善。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuzen

您的资助将帮助我创作更好的作品

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值