linux下使用openssl对socket通信加密

来源:互联网 发布:色选机 知乎 编辑:程序博客网 时间:2024/05/20 11:51

普通socket编程

TCP服务器端

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int main(int argc, char *argv[]){    int server_sockfd;//服务器端套接字    int client_sockfd;//客户端套接字    int len;    struct sockaddr_in my_addr;   //服务器网络地址结构体    struct sockaddr_in remote_addr; //客户端网络地址结构体    int sin_size;    char buf[BUFSIZ];  //数据传送的缓冲区    memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零    my_addr.sin_family=AF_INET; //设置为IP通信    my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上    my_addr.sin_port=htons(8000); //服务器端口号    /*创建服务器端套接字--IPv4协议,面向连接通信,TCP协议*/    if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)    {          perror("socket");        return 1;    }        /*将套接字绑定到服务器的网络地址上*/    if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)    {        perror("bind");        return 1;    }    /*监听连接请求--监听队列长度为5*/    listen(server_sockfd,5);    sin_size=sizeof(struct sockaddr_in);    /*等待客户端连接请求到达*/    if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size))<0)    {        perror("accept");        return 1;    }    printf("accept client %s/n",inet_ntoa(remote_addr.sin_addr));    len=send(client_sockfd,"Welcome to my server/n",21,0);//发送欢迎信息    /*接收客户端的数据并将其发送给客户端--recv返回接收到的字节数,send返回发送的字节数*/    while((len=recv(client_sockfd,buf,BUFSIZ,0))>0))    {        buf[len]='/0';        printf("%s/n",buf);        if(send(client_sockfd,buf,len,0)<0)        {            perror("write");            return 1;        }    }    close(client_sockfd);    close(server_sockfd);        return 0;}

TCP客户端编程(socket_comunication_client.c)

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int main(int argc, char *argv[]){    int client_sockfd;    int len;    struct sockaddr_in remote_addr; //服务器端网络地址结构体    char buf[BUFSIZ];  //数据传送的缓冲区    memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零    remote_addr.sin_family=AF_INET; //设置为IP通信    remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址    remote_addr.sin_port=htons(8000); //服务器端口号    /*创建客户端套接字--IPv4协议,面向连接通信,TCP协议*/    if((client_sockfd=socket(PF_INET,SOCK_STREAM,0))<0)    {        perror("socket");        return 1;    }    /*将套接字绑定到服务器的网络地址上*/    if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0)    {        perror("connect");        return 1;    }    printf("connected to server/n");    len=recv(client_sockfd,buf,BUFSIZ,0);//接收服务器端信息         buf[len]='/0';    printf("%s",buf); //打印服务器端信息    /*循环的发送接收信息并打印接收信息--recv返回接收到的字节数,send返回发送的字节数*/    while(1)    {        printf("Enter string to send:");        scanf("%s",buf);        if(!strcmp(buf,"quit")            break;        len=send(client_sockfd,buf,strlen(buf),0);        len=recv(client_sockfd,buf,BUFSIZ,0);        buf[len]='/0';        printf("received:%s/n",buf);    }    close(client_sockfd);//关闭套接字         return 0;}

以上代码转载自linux socket编程

Openssl AES加密

  1. 首先安装openssl和相关库(Ubuntu)
    apt-get install openssl libssl-dev
  2. 编写相关加密解密代码
  • aes_options.h
#ifndef _ASE_H_    #define _ASE_H_     int encrypt(char *input_string, char **encrypt_string);     void decrypt(char *encrypt_string, char **decrypt_string, int len);#endif
  • aes_options.c
#include <stdio.h>#include <openssl/aes.h>#include <stdlib.h>#include <string.h>int encrypt(char *input_string, char **encrypt_string){    AES_KEY aes;    unsigned char key[AES_BLOCK_SIZE];        // AES_BLOCK_SIZE = 16    unsigned char iv[AES_BLOCK_SIZE];        // init vector    unsigned int len;        // encrypt length (in multiple of AES_BLOCK_SIZE)    unsigned int i;    // set the encryption length    len = 0;    if ((strlen(input_string) + 1) % AES_BLOCK_SIZE == 0)     {        len = strlen(input_string) + 1;    }     else     {        len = ((strlen(input_string) + 1) / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;    }    // Generate AES 128-bit key    for (i=0; i<16; ++i) {        key[i] = 32 + i;    }    // Set encryption key    for (i=0; i<AES_BLOCK_SIZE; ++i) {        iv[i] = 0;    }    if (AES_set_encrypt_key(key, 128, &aes) < 0) {        fprintf(stderr, "Unable to set encryption key in AES\n");        exit(0);    }    // alloc encrypt_string    *encrypt_string = (unsigned char*)calloc(len, sizeof(unsigned char));        if (*encrypt_string == NULL) {        fprintf(stderr, "Unable to allocate memory for encrypt_string\n");        exit(-1);    }    // encrypt (iv will change)    AES_cbc_encrypt(input_string, *encrypt_string, len, &aes, iv, AES_ENCRYPT);    return len;}void decrypt(char *encrypt_string, char **decrypt_string,int len){    unsigned char key[AES_BLOCK_SIZE];        // AES_BLOCK_SIZE = 16    unsigned char iv[AES_BLOCK_SIZE];        // init vector    AES_KEY aes;    int i;    // Generate AES 128-bit key    for (i=0; i<16; ++i) {        key[i] = 32 + i;    }    // alloc decrypt_string    *decrypt_string = (unsigned char*)calloc(len, sizeof(unsigned char));    if (*decrypt_string == NULL) {        fprintf(stderr, "Unable to allocate memory for decrypt_string\n");        exit(-1);    }    // Set decryption key    for (i=0; i<AES_BLOCK_SIZE; ++i) {        iv[i] = 0;    }    if (AES_set_decrypt_key(key, 128, &aes) < 0) {        fprintf(stderr, "Unable to set decryption key in AES\n");        exit(-1);    }    // decrypt    AES_cbc_encrypt(encrypt_string, *decrypt_string, len, &aes, iv,             AES_DECRYPT);}

修改普通socket的代码

在修改地方加上了 //add或者modified注释
服务器端

#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include "aes_options.h"   //addint main(){    int server_fd;    int client_fd;    int len;    struct sockaddr_in server_addr;    struct sockaddr_in client_addr;    int sin_size;    char buffer[BUFSIZ];    // printf("%d",BUFSIZ);    memset(&server_addr, 0, sizeof(server_addr));  //initialize struct    memset(&server_addr, 0, sizeof(client_addr));    server_addr.sin_family = AF_INET;    server_addr.sin_addr.s_addr = INADDR_ANY;    server_addr.sin_port = htons(9000);    if((server_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)   //create server socket    {        perror("socket create failed");        return 1;    }    if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0) //bind info on server socket    {        perror("bind failed");        return 1;    }    listen(server_fd, 5);   //listen port 9000     sin_size = sizeof(struct sockaddr_in);    if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) < 0)    {        perror("accept failed");        return 1;       }    printf("accept client %s\n", inet_ntoa(client_addr.sin_addr));    len = send(client_fd, "Welcome to my server\n", 21, 0);    while((len=recv(client_fd, buffer, BUFSIZ, 0)) > 0)    {        char *decryto_string = NULL;                          //add        decrypt(buffer, &decryto_string, len);                //add        printf("%s \n", decryto_string);        if(send(client_fd, decryto_string, len, 0) < 0)       //modified        {            perror("send failed");            return 1;        }    }    close(client_fd);    close(server_fd);    return 0;}

客户端

#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include "aes_options.h"           //addint main(){    int len;    int client_sockfd;      struct sockaddr_in server_addr;    char buffer[BUFSIZ];    char *encrypt_string = NULL;    memset(&server_addr, 0, sizeof(server_addr));    server_addr.sin_family = AF_INET;    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");    server_addr.sin_port = htons(9000);    if((client_sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)    {        perror("socket create failed");        return 1;    }    if(connect(client_sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)    {        perror("connect failed");        return 1;    }    printf("connect to server\n");    len = recv(client_sockfd, buffer, BUFSIZ, 0);    buffer[len] = '\0';    printf("%s", buffer);    while(1)    {        printf("enter a data:");        scanf("%s", buffer);        if(!strcmp(buffer,"quit"))            break;        int encrypt_length = encrypt(buffer, &encrypt_string);     //add        len = send(client_sockfd, encrypt_string, encrypt_length, 0); //add        len = recv(client_sockfd, buffer, BUFSIZ, 0);        buffer[len] = '\0';        printf("recived:%s \n", buffer);    }    close(client_sockfd);    printf("bye");    return 0;}

解释说明

  1. 文件aes_options.haes_options.c里面为两个函数,第一个为加密,第二个为解密.
  2. 在socket的两个文件中引入aes_options.h即可使用两个函数..
  3. 编译的时候需要执行如下命令:
gcc aes_options.c socket_comunication_server.c -o server -lcryptogcc aes_options.c socket_comunication_client.c -o client -lcrypto## 标题文字 ##
0 0