ssl/tls服务通信示例代码
博客专区 > moodlxs 的博客 > 博客详情
ssl/tls服务通信示例代码
moodlxs 发表于1年前
ssl/tls服务通信示例代码
  • 发表于 1年前
  • 阅读 16
  • 收藏 0
  • 点赞 0
  • 评论 0

注意:使用相同的ca生成两个证书,一个是server.cer,一个是client.cer,注意生成server.cer的时候必须指明证书可以用于服务端的。

server端:

#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"

#include  <unistd.h>
#include  <sys/types.h>       /* basic system data types */
#include  <sys/socket.h>      /* basic socket definitions */
#include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include  <arpa/inet.h>       /* inet(3) functions */
#include <sys/epoll.h> /* epoll function */
#include <fcntl.h>     /* nonblocking */
#include <sys/resource.h> /*setrlimit */

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define EXIT_IF_TRUE(x) if (x)                              \
do {                                                    \
    fprintf(stderr, "Check '%s' is true\n", #x);    \
        ERR_print_errors_fp(stderr);                    \
        exit(2);                                        \
}while(0)

int main(int argc, char **argv)
{
    SSL_CTX     *ctx;
    SSL         *ssl;
    X509        *client_cert;

    char szBuffer[1024];
    int nLen;

    struct sockaddr_in addr;
    int len;
    int nListenFd, nAcceptFd;

    // 初始化
    SSLeay_add_ssl_algorithms();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    ERR_load_BIO_strings();

    // 我们使用SSL V3,V2
    EXIT_IF_TRUE((ctx = SSL_CTX_new (SSLv23_method())) == NULL);

    // 要求校验对方证书
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

    // 加载CA的证书
    EXIT_IF_TRUE (!SSL_CTX_load_verify_locations(ctx, "cacert.cer", NULL));

    // 加载自己的证书
    EXIT_IF_TRUE (SSL_CTX_use_certificate_file(ctx, "server.cer", SSL_FILETYPE_PEM) <= 0) ;

    // 加载自己的私钥
    EXIT_IF_TRUE (SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM) <= 0) ;

    // 判定私钥是否正确
    EXIT_IF_TRUE (!SSL_CTX_check_private_key(ctx));

    // 创建并等待连接
    nListenFd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in servaddr;
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
    servaddr.sin_port = htons (19821);

    if (bind(nListenFd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) 
    {
        perror("bind error");
        return -1;
    }

    if (listen(nListenFd, 1024) == -1) 
    {
        perror("listen error");
        return -1;
    }

    memset(&addr, 0, sizeof(addr));
    len = sizeof(addr);
    nAcceptFd = accept(nListenFd, (struct sockaddr *)&addr, (socklen_t *)&len);
    printf("Accept a connect from [%s:%d]\n", 
            inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

    // 将连接付给SSL
    EXIT_IF_TRUE( (ssl = SSL_new (ctx)) == NULL);
    SSL_set_fd (ssl, nAcceptFd);
    EXIT_IF_TRUE( SSL_accept (ssl) != 1);

    // 进行操作
    memset(szBuffer, 0, sizeof(szBuffer));
    nLen = SSL_read(ssl,szBuffer, sizeof(szBuffer));
    fprintf(stderr, "Get Len %d %s ok\n", nLen, szBuffer);
    strcat(szBuffer, " this is from server");
    SSL_write(ssl, szBuffer, strlen(szBuffer));

    // 释放资源
    SSL_free (ssl);
    SSL_CTX_free (ctx);
    close(nAcceptFd);
}

 

客户端:

#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"

#include  <unistd.h>
#include  <sys/types.h>       /* basic system data types */
#include  <sys/socket.h>      /* basic socket definitions */
#include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include  <arpa/inet.h>       /* inet(3) functions */
#include <sys/select.h>       /* select function*/

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>


#define EXIT_IF_TRUE(x) if (x)    \
do {                                                    \
    fprintf(stderr, "Check '%s' is true\n", #x);    \
        ERR_print_errors_fp(stderr);                    \
        exit(2);                                        \
}while(0)

int main(int argc, char **argv)
{
    SSL_METHOD  *meth;
    SSL_CTX     *ctx;
    SSL         *ssl;

    int nFd;
    int nLen;
    char szBuffer[1024];

    // 初始化
    SSLeay_add_ssl_algorithms();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    ERR_load_BIO_strings();

    // 我们使用SSL V3,V2    
    EXIT_IF_TRUE((ctx = SSL_CTX_new (SSLv23_method())) == NULL);

    // 要求校验对方证书
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

    // 加载CA的证书
    EXIT_IF_TRUE (!SSL_CTX_load_verify_locations(ctx, "cacert.cer", NULL));

    // 加载自己的证书
    EXIT_IF_TRUE (SSL_CTX_use_certificate_file(ctx, "client.cer", SSL_FILETYPE_PEM) <= 0) ;

    // 加载自己的私钥
    EXIT_IF_TRUE (SSL_CTX_use_PrivateKey_file(ctx, "client.key", SSL_FILETYPE_PEM) <= 0) ;

    // 判定私钥是否正确
    EXIT_IF_TRUE (!SSL_CTX_check_private_key(ctx));

    // 创建连接
    nFd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in servaddr;
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(19821);
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);

    if (connect(nFd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        perror("connect error");
        return -1;
    }

    // 将连接付给SSL
    EXIT_IF_TRUE( (ssl = SSL_new (ctx)) == NULL);
    SSL_set_fd (ssl, nFd);
    EXIT_IF_TRUE( SSL_connect (ssl) != 1);

    // 进行操作
    sprintf(szBuffer, "this is from client %d", getpid());
    SSL_write(ssl, szBuffer, strlen(szBuffer));

    // 释放资源
    memset(szBuffer, 0, sizeof(szBuffer));
    nLen = SSL_read(ssl,szBuffer, sizeof(szBuffer));
    fprintf(stderr, "Get Len %d %s ok\n", nLen, szBuffer);

    SSL_free (ssl);
    SSL_CTX_free (ctx);
    close(nFd);
}

 

共有 人打赏支持
粉丝 7
博文 41
码字总数 168307
×
moodlxs
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: