可以利用OpenSSL库中提供的函数来动态生成证书和私钥文件,或者将证书和私钥文件放到程序的代码里。
以下是一个简单的例子,可以在程序中生成自签名的证书和私钥文件:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#define PORT 4433
#define BACKLOG 10
void* handle_client(void* arg) {
SSL* ssl = (SSL*) arg;
char buffer[1024];
int bytes;
const char* welcome = "Welcome to the server!\n";
SSL_write(ssl, welcome, strlen(welcome));
while (1) {
bytes = SSL_read(ssl, buffer, sizeof(buffer));
if (bytes > 0) {
buffer[bytes] = '\0';
printf("[Client]: %s", buffer);
if (strcmp(buffer, "bye\n") == 0) {
const char* bye = "Goodbye!\n";
SSL_write(ssl, bye, strlen(bye));
break;
}
}
}
SSL_shutdown(ssl);
SSL_free(ssl);
close((intptr_t) arg);
pthread_exit(NULL);
}
int main() {
SSL_CTX* ctx;
pthread_t tid;
int server_fd, client_fd;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
// 生成自签名的证书和私钥文件
EVP_PKEY* pkey = EVP_PKEY_new();
RSA* rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);
EVP_PKEY_assign_RSA(pkey, rsa);
X509* x509 = X509_new();
X509_set_version(x509, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
X509_set_pubkey(x509, pkey);
X509_NAME* name = X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char*) "localhost", -1, -1, 0);
X509_set_issuer_name(x509, name);
X509_sign(x509, pkey, EVP_sha256());
FILE* cert_file = fopen("server.crt", "w");
PEM_write_X509(cert_file, x509);
fclose(cert_file);
FILE* key_file = fopen("server.key", "w");
PEM_write_PrivateKey(key_file, pkey, NULL, NULL, 0, NULL, NULL);
fclose(key_file);
ctx = SSL_CTX_new(TLSv1_2_server_method());
if (!ctx) {
printf("Failed to create SSL context\n");
exit(EXIT_FAILURE);
}
if (SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM) < 0) {
printf("Failed to load server certificate\n");
exit(EXIT_FAILURE);
}
if (SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM) < 0 ) {
printf("Failed to load server private key\n");
exit(EXIT_FAILURE);
}
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
printf("Failed to create socket\n");
exit(EXIT_FAILURE);
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
printf("Failed to bind socket\n");
exit(EXIT_FAILURE);
}
if (listen(server_fd, BACKLOG) < 0) {
printf("Failed to listen on socket\n");
exit(EXIT_FAILURE);
}
while (1) {
client_fd = accept(server_fd, NULL, NULL);
if (client_fd < 0) {
printf("Failed to accept client connection\n");
continue;
}
SSL* ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_fd);
if (SSL_accept(ssl) <= 0) {
printf("Failed to establish SSL connection\n");
SSL_free(ssl);
close(client_fd);
continue;
}
pthread_create(&tid, NULL, handle_client, ssl);
pthread_detach(tid);
}
SSL_CTX_free(ctx);
close(server_fd);
return 0;
}
```
这个程序会先生成一个2048位的RSA密钥对,然后使用RSA密钥对生成一个自签名的X.509证书,并将证书和私钥文件写入到当前目录下的`server.crt`和`server.key`文件中。这样就可以动态生成证书和私钥文件,无需手动创建和管理。