Skip to content

证书生成实操 ​

下面是干什么?

利用openssl,生成一个服务端证书,以便客户端与服务端连接时,客户端可以对服务端的身份进行单向认证。

在本例中我们自己是CA,也是服务端。

  1. 使用rsa算法生成一个server.key文件 里边包含一个秘钥对。 在rsa中 既可以公钥加密 私钥解密,也可以私钥解密 公钥加密。
c++
openssl genrsa -out server.key 2048

//如果想从server.key文件中导出公钥和私钥
openssl rsa -in server.key -pubout -out server.pub
openssl rsa -in server.key -out private.key
  1. 生成一个证书请求 server.csr
c++
openssl req -new -key server.key -out server.csr
  1. ca用其私钥对csr证书请求进行签名 生成x509标准证书 server.crt
c++
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

有了CA签名过的crt证书以后,服务端只需要安装该证书,客户端在与服务端进行ssl握手时就可以对服务端的身份进行单向认证了。

证书原理示意图 ​

image

例子 (Linux下) ​

下面是干什么?

一个是ssl客户端 一个是ssl服务端 实现https。

两个例子都是camke构建的, 记得在cmake中导入openssl的静态库 libssl 和 libcrypto

cmake
cmake_minimum_required(VERSION 2.6)

project(C_EPOLL_SERVER)

include_directories(${CMAKE_SOURCE_DIR}/include)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_options("-Wall")

set(CMAKE_BUILD_TYPE "Debug")

add_executable(../main src/main.cpp)

target_link_libraries(../main /usr/lib64/libssl.so /usr/lib64/libcrypto.so)
1.纯socket和openssl实现https协议的ssl_client访问百度一下。
c++
#include <cstdio>
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/uio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string>
#include <unistd.h>
using namespace std;
int main()
{
    //初始化SSL库
    SSL_library_init();  
    SSL_load_error_strings();

    //请求百度服务器 443端口
    //110.242.68.3是百度ip
    std::string server_ip = "110.242.68.3";
    short server_port = 443;
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    cout << "Socket created\n";

     // 设置服务器地址和端口
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(server_port); // 服务器端口号
    server_addr.sin_addr.s_addr = inet_addr(server_ip.c_str()); // 服务器IP地址

    // TCP三次握手
    connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));

    // 创建SSL上下文
    //SSLv23_client_method 客户端支持的协议版本 会发送给服务端
    //也可以改成TLSv1_1_client_method();
    SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
    
    
    // 创建SSL对象
    SSL *ssl = SSL_new(ctx);
    SSL_set_fd(ssl, sock);

    // SSL握手
    cout<< SSL_connect(ssl) <<"\n";

    // 构造个http请求 并且往对端同步发送
    // 加密过的ssl数据
    std::string  http_rep = 
    "GET /s?wd=happy HTTP/1.1\r\n"
    "Host: "+server_ip+":"+ std::to_string(server_port)+"\r\n" 
    "Connection: keep-alive\r\n\r\n";
    std::cout<<http_rep<<"\n";
    SSL_write(ssl, http_rep.c_str(), http_rep.size());

    // 同步接收服务端发回的http报文
    char http_res[1024];
    int len = 0;
    int flag = 0;
    while((len = SSL_read(ssl, http_res,sizeof(http_res)))> 0){
        std::cout<<"reply: " <<std::string(http_res)<<"\n";
    }

    getchar();
    
    //关闭ssl连接 
    SSL_shutdown(ssl);
    SSL_free(ssl);
    SSL_CTX_free(ctx);

    //四次挥手
    close(sock);

    std::cout<<"\n";
    return 0;
}

2.tcp_socket和openssl实现ssl_server
c++
#include <functional>
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <string.h>
#include <sys/uio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
using namespace std;

int main()
{
    // 初始化OpenSSL库
    SSL_library_init();
    SSL_load_error_strings();


    int sock = socket(AF_INET, SOCK_STREAM, 0);
    cout<<"Socket created";
    
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8083);
    addr.sin_addr.s_addr = INADDR_ANY;
    
    cout<< bind(sock,(struct sockaddr*)&addr,sizeof(addr))<<"\n";

    cout<< listen(sock, 10) <<"\n";

    // 创建SSL上下文
    SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());

    // 加载被CA签名过的服务端证书 (如果没有CA签名,浏览器访问的时候提示不安全)
    SSL_CTX_use_certificate_file(ctx, "/root/server.crt", SSL_FILETYPE_PEM);

    // 加载服务端私钥
    SSL_CTX_use_PrivateKey_file(ctx, "/root/server.key", SSL_FILETYPE_PEM);

    struct sockaddr_in cilent_addr;
    while (1) {
        socklen_t size;
        std::cout<<"等待连接"<<"\n";
        memset(&cilent_addr,0,sizeof(cilent_addr));
        int client_sock = accept(sock, (struct sockaddr*)&cilent_addr, &size);

        // 创建SSL对象
        SSL *ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client_sock);

        // SSL握手(服务端阻塞在这里 等客户端SSL_connect(ssl))
        cout<< SSL_accept(ssl)<<"\n";

        std::string http_rep = "HTTP/1.1 200 OK\r\n"
                                "Accept-Ranges: bytes\r\n"
                                "Cache-Control: no-cache\r\n"
                                "Connection: keep-alive\r\n\r\n";
        std::string html = "<html><body><h1>Welcome</h1></body></html>\r\n\r\n";

        SSL_write(ssl, http_rep.c_str(), http_rep.size());
        SSL_write(ssl, html.c_str(), html.size());
  
    }


    std::cout<<"\n";
    return 0;
}

常用接口 ​

imageimageimage


原理好文 ​

什么是单项加密、对称加密、非对称加密、证书、秘钥、SSL/TLS原理? https://my.oschina.net/helloworldnet/blog/5587819

学 习 记 录