1. 程式人生 > >linux使用openssl對socket通訊加密

linux使用openssl對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客戶端

#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;
}

/*********************openssl加密解密函式******************************/

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);
}

/***********將普通的tcp伺服器及客戶端進行加密處理************************/
//伺服器

#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"   //add

int 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"           //add

int 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;
}

//編譯時

gcc aes_options.c socket_comunication_server.c -o server -lcrypto
gcc aes_options.c socket_comunication_client.c -o client -lcrypto## 標題文字 ##