• 2017-2018-1 20155332 实验五 通信协议设计


    2017-2018-1 20155332 实验五 通信协议设计

    实验内容

    研究OpenSSL算法,测试对称算法中的AES,非对称算法中的RSA,Hash算法中的MD5
    选用合适的算法,基于混合密码系统实现对TCP通信进行机密性、完整性保护。

    2.在Ubuntu中实现对实验二中的“wc服务器”通过混合密码系统进行防护

    实验截图 已经在蓝墨云班课提交

    实验步骤

    任务一 Linux下OpenSSL的安装与测试

    任务要求:在Ubuntu中完成 http://www.cnblogs.com/rocedu/p/5087623.html 中的作业

    1.安装指南
    到OpenSSL官网,选择打开OpenSSL源码载地址,按照下图所示方法下载压缩包“openssl-master.zip”
    2.安装命令

    $ ./config
    $ make
    $ make test
    $ make install

    3.安装测试
    用老师教程中的test_openssl.c例子进行测试

    	#include <stdio.h>
    	#include <openssl/evp.h>
    
    	int main(){
        
        OpenSSL_add_all_algorithms();
        
        return 0;
        }
    
    

    4.编译运行
    使用命令gcc -o test_openssl test_openssl.c -L/usr/local/ssl/lib -lcrypto -ldl -lpthread编译,结果生成可执行文件test_openssl

    并执行echo $?,结果打印0,测试结果表明安装成功。

    【对编译命令的一点说明:-L选项——指定链接库的文件夹地址;-lcrypto——导入OpenSSL所需包;-ldl选项——加载动态库;-lpthread选项——链接POSIX thread库】

    任务二

    任务要求:在Ubuntu中实现对实验二中的“wc服务器”通过混合密码系统进行防护

    实验步骤

    1. OpenSSL初始化
    2. 选择会话协议
    3. 创建会话环境
    4. 建立SSL套接字
    5. 完成SSL握手
    6. 进行数据传输
    7. 结束SSL通信

    实验代码

    #include<netinet/in.h>                         // for sockaddr_in  
    #include<sys/types.h>                          // for socket  
    #include<sys/socket.h>                         // for socket  
    #include<stdio.h>                              // for printf  
    #include<stdlib.h>                             // for exit  
    #include<string.h>                 // for bzero 
    #include<memory.h> 
    #include<time.h>                            
    #include<openssl/rsa.h>
    #include<openssl/pem.h>
    #include<openssl/err.h>
    #include <openssl/aes.h>
    #pragma comment(lib,"libeay32.lib")
    #define OPENSSLKEY "test.key"
    #define PUBLICKEY "test_pub.key"
    #define BUFFSIZE 1024  
    #define HELLO_WORLD_SERVER_PORT       6000 
    #define BUFFER_SIZE                   1024  
    #define FILE_NAME_MAX_SIZE            512  
    int mywc(char file_name[],int choose);
    char* my_encrypt(char *str,char *path_key);//rsa加密
    char* my_decrypt(char *str,char *path_key);//rsa解密
    void aes_encrypt(char *str,char aes_keybuf[],char buf[]);//aes加密
    void aes_decrypt(char *str,char aes_keybuf[],char buf[]);//aes解密
    int main(int argc, char **argv)  
    {  
        
        FILE *fp;
        if (argc != 2)  
        {  
            printf("Usage: ./%s ServerIPAddress
    ", argv[0]);  
            exit(1);  
        }  
    
    // 设置一个socket地址结构client_addr, 代表客户机的internet地址和端口  
        struct sockaddr_in client_addr;  
        bzero(&client_addr, sizeof(client_addr));  
        client_addr.sin_family = AF_INET;   
        client_addr.sin_addr.s_addr = htons(INADDR_ANY); // INADDR_ANY表示自动获取本机地址  
        client_addr.sin_port = htons(0); 
    
    // 创建字节流socket,用client_socket代表客户端socket  
        int client_socket = socket(AF_INET, SOCK_STREAM, 0);  
        if (client_socket < 0)  
        {  
            printf("Create Socket Failed!
    ");  
            exit(1);  
        }  
    
    // 把客户端的socket和客户端的socket地址结构绑定   
        if (bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)))  
        {  
            printf("Client Bind Port Failed!
    ");  
            exit(1);  
        }  
    
    // 设置一个socket地址结构server_addr,代表服务器的internet地址和端口  
        struct sockaddr_in  server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
    
    // 服务器的IP地址来自程序的参数   
        if (inet_aton(argv[1], &server_addr.sin_addr) == 0) //一个字符串IP地址转换为一个32位的网络序列IP地址,也可以用inet_addr
        {  
            printf("Server IP Address Error!
    ");  
            exit(1);  
        }                                                                                                               
        server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
        int server_addr_length = sizeof(server_addr);   
    
            // 向服务器发起连接请求,连接成功后client_socket代表客户端和服务器端的一个socket连接  
            if (connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length)==-1)  
            {  
                printf("Can Not Connect To %s!
    ", argv[1]);  
                exit(1);  
            }  
    
            char file_name[FILE_NAME_MAX_SIZE];  
            bzero(file_name, sizeof(file_name));  
            printf("Please Input File Name.	");  
            scanf("%s", file_name);  
            if((fp = fopen(file_name,"r"))==NULL)
                {
                    printf("Failure to open %s
    ",file_name);
                    exit(0);
            }
        
            char buffer[BUFFER_SIZE];  
            bzero(buffer, sizeof(buffer));  
            strcpy(buffer,file_name);
            if(send(client_socket,buffer,BUFFER_SIZE,0)==-1)
            {
                printf("发送文件名失败
    ");
            }
            printf("发送文件名成功
    ");
            bzero(buffer, sizeof(buffer)); 
            //利用伪随机数生成32字节会话密钥:
            unsigned char aes_keybuf[32];
            int i;
            srand((unsigned) time(NULL));
            for(i=0;i<32;i++)
            {
                aes_keybuf[i]=rand()%10+48;
            }
            //用rsa对会话密钥加密
            char *aeskey_en;
            aeskey_en=my_encrypt(aes_keybuf,PUBLICKEY);
            printf("会话密钥:%s
    加密后的会话密钥为%s
    
    
    ",aes_keybuf,aeskey_en);
            if((send(client_socket, aeskey_en, strlen(aeskey_en)+1, 0))==-1)
            {
                printf("发送文件失败
    ");
            }
            printf("发送密钥完毕,长度为%d
    ",strlen(aeskey_en)+1);
            printf("是否发送密文?y or n
    ");
            char choose;
            char ch;while((ch=getchar())!='
    '&&ch!=EOF);
            scanf("%c",&choose);
            if(choose=='y')
        {//使用会话密钥对消息进行aes加密
            char ptr_en[512],ptr_de[512];       
            char ch;
            
            i=0;
            while((ch=fgetc(fp))!=EOF)
            {
                buffer[i++]=ch;
                if(i>=BUFFER_SIZE)
                {
                    printf("加密前 %s
    ",buffer);
                    aes_encrypt(buffer,aes_keybuf,ptr_en);              
                    
                    //printf("加密后发送密文 %s
    ",ptr_en);
                                         
                    if((send(client_socket, ptr_en, strlen(ptr_en), 0))==-1)
                    {
                        printf("发送文件失败
    ");
                    }
                    printf("发送密文长度 :%d
    ",strlen(ptr_en));
                    bzero(ptr_en, sizeof(ptr_en));
                    bzero(buffer, sizeof(buffer));
                    i=0;
                }
            }
            if(i<BUFFER_SIZE)
            {
                
                printf("加密前消息 %s
    ",buffer);            
                aes_encrypt(buffer,aes_keybuf,ptr_en);          
                
                printf("加密后发送密文 %s
    ",ptr_en);
                //ptr_de=my_decrypt(buffer,OPENSSLKEY);//解密buffer
                
                if((send(client_socket, ptr_en, strlen(ptr_en), 0))==-1)
                {
                    printf("发送文件失败
    ");
                }
                printf("发送密文长度 :%d
    ",strlen(ptr_en));
                
            }
            bzero(buffer, sizeof(buffer));
            printf("发送密文完毕
    ");
            }
            /*
            if(ptr_en!=NULL){
                    free(ptr_en);
                } */ 
            mywc(file_name,1);
            mywc(file_name,2);
    
            bzero(buffer, sizeof(buffer));
    
            fclose(fp);
         
            close(client_socket); // 传输完毕,关闭socket  
            return 0;  
    
    }  
    int mywc(char file_name[],int choose)
    {
        FILE *fp;
            char ch;
            int flag=0,num=0;
           // int choose;
           //  printf("统计单词个数还是实现“wc -w”?(1or2)
    ");
           // scanf("%d",&choose);
        if((fp = fopen(file_name,"r"))==NULL)
        {
             printf("Failure to open %s
    ",file_name);
                 exit(0);
            }
                 
        if(choose==1)
        {
            while((ch=fgetc(fp))!=EOF)
            {
                if(ch==' ' || ch=='
    ' || ch=='	' ||  ch=='!' || ch=='?' || ch=='"' || ch=='.' || ch== '\,' || ch==':' || ch=='(' || ch==')' || ch==';'     || ch=='-')
                {
                    flag=0;
                }
                else
                {
                    if(flag==0)
                    {
                        flag=1;
                        num++;
                    }
                              
                }
    
            }
    
        }
        else if(choose==2)
        {
            while((ch=fgetc(fp))!=EOF)
            {
                if(ch==' ' || ch=='
    ' || ch=='	' || ch=='
    ')
                    flag=0;
                else
                {
                    if(flag==0)
                    {
                        flag=1;
                        num++;
                    }
                }
            }
        }
        printf("单词个数为:%d_用方式%d计算
    ",num,choose);
        fclose(fp);
        return num;
    }
    char *my_encrypt(char *str,char *path_key){
        char *p_en;
        RSA *p_rsa;
        FILE *file;
        int flen,rsa_len;
        if((file=fopen(path_key,"r"))==NULL){
            perror("open key file error");
            return NULL;    
        }   
        if((p_rsa=PEM_read_RSA_PUBKEY(file,NULL,NULL,NULL))==NULL){
        //if((p_rsa=PEM_read_RSAPublicKey(file,NULL,NULL,NULL))==NULL){   换成这句死活通不过,无论是否将公钥分离源文件
            ERR_print_errors_fp(stdout);
            return NULL;
        }   
        flen=strlen(str);
        rsa_len=RSA_size(p_rsa);
        p_en=(unsigned char *)malloc(rsa_len+1);
        memset(p_en,0,rsa_len+1);
        if(RSA_public_encrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_en,p_rsa,RSA_NO_PADDING)<0){
            return NULL;
        }
        RSA_free(p_rsa);
        fclose(file);
        return p_en;
    }
    char *my_decrypt(char *str,char *path_key){
        char *p_de;
        RSA *p_rsa;
        FILE *file;
        int rsa_len;
        if((file=fopen(path_key,"r"))==NULL){
            perror("open key file error");
            return NULL;
        }
        if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
            ERR_print_errors_fp(stdout);
            return NULL;
        }
        rsa_len=RSA_size(p_rsa);
        p_de=(unsigned char *)malloc(rsa_len+1);
        memset(p_de,0,rsa_len+1);
        if(RSA_private_decrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_de,p_rsa,RSA_NO_PADDING)<0){
            return NULL;
        }
        RSA_free(p_rsa);
        fclose(file);
        return p_de;
    }
    void aes_encrypt(char *str,char aes_keybuf[],char buf[]){
        
        AES_KEY aeskey;
        AES_set_encrypt_key(aes_keybuf,256,&aeskey);
        for(int i=0;i<sizeof(str);i+=16)
        AES_encrypt(str+i,buf+i,&aeskey);
        //printf("
    
    in_加密后:%s
    
    
    ",buf);
           
    }
    void aes_decrypt(char *str,char aes_keybuf[],char buf[]){
        
        AES_KEY aeskey;
        AES_set_decrypt_key(aes_keybuf,256,&aeskey);
        for(int i=0;i<sizeof(str);i+=16)
        AES_decrypt(str+i,buf+i,&aeskey);
        
    
    }
    
    
    #include<netinet/in.h>   
    #include<sys/types.h>   
    #include<sys/socket.h>   
    #include<stdio.h>   
    #include<stdlib.h>   
    #include<string.h>   
    #include<pthread.h> 
    #include<memory.h> 
    #include<openssl/rsa.h>
    #include<openssl/pem.h>
    #include<openssl/err.h>
    #include <openssl/aes.h>
    #pragma comment(lib,"libeay32.lib")
    #define OPENSSLKEY "test.key"
    #define PUBLICKEY "test_pub.key"
    #define BUFFSIZE 1024
    #define HELLO_WORLD_SERVER_PORT    6000 
    #define LENGTH_OF_LISTEN_QUEUE     20  
    #define BUFFER_SIZE                1024  
    #define FILE_NAME_MAX_SIZE         512  
    char* my_encrypt(char *str,char *path_key);//rsa加密
    char* my_decrypt(char *str,char *path_key);//rsa解密
    void aes_encrypt(char *str,char aes_keybuf[],char buf[]);//aes加密
    void aes_decrypt(char *str,char aes_keybuf[],char buf[]);//aes解密
    void *process_client(void *new_server_socket);
    int mywc(char file_name[])
    {
        char ch;
        int flag=0,num=0;
        int choose;
        FILE *fp;
        printf("统计单词个数还是实现“wc -w”?(1or2)
    ");
        scanf("%d",&choose);
        if((fp = fopen(file_name,"r"))==NULL)
        {
            printf("Failure to open %s
    ",file_name);
            exit(0);
        }
    
        if(choose==1)
        {
        while((ch=fgetc(fp))!=EOF)
        {
            if(ch==' ' || ch=='
    ' || ch=='	' ||  ch=='!' || ch=='?' || ch=='"' || ch=='.' || ch== '\,' || ch==':' || ch=='(' || ch==')' || ch==';' || ch=='-')
            {
                flag=0;
            }
            else
            {
                if(flag==0)
                {
                    flag=1;
                    num++;
                }
    
            }          
        }
        }
        else if(choose==2)
        {
            while((ch=fgetc(fp))!=EOF)
            {
                if(ch==' ' || ch=='
    ' || ch=='	' || ch=='
    ')
                    flag=0;
                else
                {
                    if(flag==0)
                    {
                        flag=1;
                        num++;
                    }
                }
            }
        }
        printf("单词个数为:%d
    ",num);
        fclose(fp);
        return num;
    }
    int main(int argc, char **argv)  
    {  
     
    // 设置一个socket地址结构server_addr,代表服务器的IP地址和端口  
        struct sockaddr_in   server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
        server_addr.sin_addr.s_addr = htons(INADDR_ANY);  
        server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
    
    // 创建字节流socket:server_socket 
        int server_socket = socket(AF_INET, SOCK_STREAM, 0);  
        if (server_socket ==-1)  
        {  
            printf("Create Socket Failed!
    ");  
            exit(1);  
        }  
    
    // 把socket和socket地址结构绑定   
        if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr))==-1)  
        {  
            printf("Server Bind Port: %d Failed!
    ", HELLO_WORLD_SERVER_PORT);  
            exit(1);  
        }  
    
    // server_socket用于监听   
        if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE)==-1)  
        {  
            printf("Server Listen Failed!
    ");  
            exit(1);  
        }  
    // 服务器端一直运行用以持续为客户端提供服务   
          
        while(1)
        {
    // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept  
     
            struct sockaddr_in client_addr;  
            int length = sizeof(client_addr);    
    // accpet返回一个新的socket,这个socket用来与此次连接到server的client进行通信  
            int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);         
            if (new_server_socket ==-1)  
            {  
                printf("Server Accept Failed!
    "); 
                exit(0); 
            }
            printf("连接到客户端
    ");
            pthread_t pid;
            if(pthread_create(&pid, NULL, process_client,(void *) &new_server_socket) < 0){
                  printf("pthread_create error
    ");
            }
            
        }
    //  close(server_socket);
    }
    void *process_client(void *new_server_socket)
    {
            int sockid=*(int *)new_server_socket;
            FILE *fp;
            //接受来自客户端的文件
            char buffer[BUFFER_SIZE]; 
            char file_name[FILE_NAME_MAX_SIZE];
            bzero(buffer, sizeof(buffer));  
            int length=0;
            if(recv(sockid,buffer,BUFFER_SIZE, 0)==-1)
            {
                printf("接受文件名%s失败
    ",buffer);
            }
            strcpy(file_name,buffer);
            strcat(file_name,"_server");
            printf("创建文件夹%s
    ",file_name);
            if((fp = fopen(file_name,"w"))==NULL)
            {
                printf("Failure to open %s
    ",file_name);
                exit(0);
            }
            bzero(buffer, sizeof(buffer));
            //接收密钥密文
            unsigned char *aes_keybuf;
    int lenn;
            if((lenn=recv(sockid, buffer,BUFFER_SIZE, 0))<0)
            {
                printf("接受密钥出错
    ");
            }
            printf("接受密钥密文  %s
    
    ",buffer);
    printf("接受密钥length  %d
    
    ",lenn);
            aes_keybuf=my_decrypt(buffer,OPENSSLKEY);//解密buffer
            printf("解密得会话密钥  %s
    
    
    ",aes_keybuf);
            bzero(buffer, sizeof(buffer));
            char ptr_en[512],ptr_de[512];
            //length = recv(sockid, buffer,BUFFER_SIZE, 0);
            //printf(" recv length :%d
    ",length);
            while( length = recv(sockid, buffer,BUFFER_SIZE, 0))
            {
                if(length<0)
                {
                    printf("接受文件出错
    ");
                    exit(0);
                }
                printf("接受密文  %s
    
    
    ",buffer);
                aes_decrypt(buffer,aes_keybuf,ptr_de);//解密buffer
                        
                printf("解密密文  %s
    ",ptr_de);
                fwrite(ptr_de,sizeof(char),strlen(ptr_de),fp)<length;
                
                bzero(buffer, sizeof(buffer));
                bzero(ptr_de, sizeof(ptr_de));
            }
            fclose(fp);
            /*if(ptr_de!=NULL){
                    free(ptr_de);
                } */
            printf("接收密文完毕
    ");
            bzero(buffer, BUFFER_SIZE);
            int number=0;
            number=mywc(file_name);
            //bzero(buffer, BUFFER_SIZE);  
            //buffer[0]=number+48;
    
                bzero(buffer, sizeof(buffer));  
             
            printf("File Transfer Finished!
    ");   
            close(new_server_socket);  
    } 
    char *my_encrypt(char *str,char *path_key){
        char *p_en;
        RSA *p_rsa;
        FILE *file;
        int flen,rsa_len;
        if((file=fopen(path_key,"r"))==NULL){
            perror("open key file error");
            return NULL;    
        }   
        if((p_rsa=PEM_read_RSA_PUBKEY(file,NULL,NULL,NULL))==NULL){
        //if((p_rsa=PEM_read_RSAPublicKey(file,NULL,NULL,NULL))==NULL){   换成这句死活通不过,无论是否将公钥分离源文件
            ERR_print_errors_fp(stdout);
            return NULL;
        }   
        flen=strlen(str);
        rsa_len=RSA_size(p_rsa);
        p_en=(unsigned char *)malloc(rsa_len+1);
        memset(p_en,0,rsa_len+1);
        if(RSA_public_encrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_en,p_rsa,RSA_NO_PADDING)<0){
            return NULL;
        }
        RSA_free(p_rsa);
        fclose(file);
        return p_en;
    }
    char *my_decrypt(char *str,char *path_key){
        char *p_de;
        RSA *p_rsa;
        FILE *file;
        int rsa_len;
        if((file=fopen(path_key,"r"))==NULL){
            perror("open key file error");
            return NULL;
        }
        if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
            ERR_print_errors_fp(stdout);
            return NULL;
        }
        rsa_len=RSA_size(p_rsa);
        p_de=(unsigned char *)malloc(rsa_len+1);
        memset(p_de,0,rsa_len+1);
        if(RSA_private_decrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_de,p_rsa,RSA_NO_PADDING)<0){
            return NULL;
        }
        RSA_free(p_rsa);
        fclose(file);
        return p_de;
    }
    void aes_encrypt(char *str,char aes_keybuf[],char buf[]){
        
        AES_KEY aeskey;
        AES_set_encrypt_key(aes_keybuf,256,&aeskey);
        for(int i=0;i<sizeof(str);i+=16)
        AES_encrypt(str+i,buf+i,&aeskey);
        
    }
    void aes_decrypt(char *str,char aes_keybuf[],char buf[]){
        
        AES_KEY aeskey;
        AES_set_decrypt_key(aes_keybuf,256,&aeskey);
        for(int i=0;i<sizeof(str);i+=16)
        AES_decrypt(str+i,buf+i,&aeskey);
        
    }
    

    任务三 Z32的国密算法的使用

  • 相关阅读:
    HDU 2544 最短路
    HDU 3367 Pseudoforest
    USACO 2001 OPEN
    HDU 3371 Connect the Cities
    HDU 1301 Jungle Roads
    HDU 1879 继续畅通工程
    HDU 1233 还是畅通工程
    HDU 1162 Eddy's picture
    HDU 5745 La Vie en rose
    HDU 5744 Keep On Movin
  • 原文地址:https://www.cnblogs.com/besti2015/p/8053871.html
Copyright © 2020-2023  润新知