zoukankan      html  css  js  c++  java
  • 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的国密算法的使用

  • 相关阅读:
    SEO工作中如何增加用户体验?10个细节要注意!
    网站优化不等于搜索引擎优化SEO
    新站不收录内页的原因及解决办法
    网站搜索引擎优化(SEO)的18条守则
    网站优化(SEO)的10大误区
    网页设计师必知的10则SEO
    站内SEO规范
    影响SEO 搜索引擎优化的网页制作细节
    推荐两个国外网站-帮你优化网站SEO和预测下期的PR值
    简单介绍百度与谷歌关于收录的不同之处
  • 原文地址:https://www.cnblogs.com/besti2015/p/8053871.html
Copyright © 2011-2022 走看看