• 《安全编程技术》实验三 socket安全编程


    一、实验目的与要求:

    (一)实验目的

    该实验为设计性实验,实验目的如下:

    1. 了解本地计算机的网络配置。
    2. 熟悉面向对象编程/C编程环境,能够编写简单程序。
    3. 熟练网络查阅源代码资源并会调试,修改,测试。

    (二)实验要求

    1. 本实验一人一组,编程语言为C/C++/C#/JAVA。
    2. 要求学生熟练掌握C/C++/C#/JAVA语言编程,多线程编程。
    3. 实验报告要求:
      • 实验报告要求包括实验目的、实验要求、实验内容(系统的设计和实现)、实验结果分析和实验体会等,重点在于实验内容(系统的设计和实现)和实验结果分析。实验报告要求上传和打印。
      • 写出系统设计和实现过程中的心得和体会,并回答实验中的思考题。
      • 实验报告撰写规范请见附。

    二、实验内容、步骤及结论

    (一)实验内容

    1. 实现简单的基于TCP或UDP的通信程序(控制台和视窗都可以),要求使用VC/JAVA/C#编程。
    2. 对完成的socket通信进行安全性设置,4项任选2项实现(1.做用户验证(用户未注册或者密码不正确,就断开连接)2.加密信息内容3.超时机制4.黑名单机制)。

    (二)代码:https://segmentfault.com/a/1190000000736700

    1.服务器端server.c

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

    2.客户端client.c

    #include <stdio.h>
    #include <stdlib.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;
    
        }
        int username;
        int password;
        printf("enter the username:");
        scanf("%d", &username);
        printf("enter the password:");
        scanf("%d", &password);
        if (username !=2020 || password != 1212)
        {
            printf("uncorrect name!\n");
            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;
    }
    
    /*char username;
        int password;
        printf("enter the username:");
        scanf("%s", &username);
        printf("enter the password:");
        scanf("%d", &password);
        if (username != "ycy" || password != 20201212)
        {
            printf("uncorrect name!\n");
            return 1;
        }
        */

    3.加密解密函数openssl.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);
    }

    4.AES头文件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

    (三)运行

    gcc -I. openssl.c server.c -o server -lcrypto
    
    gcc -I. openssl.c client.c -o client -lcrypto

    先运行server,再运行client

    输入quit退出

    若用户名或密码错误,无法进入

     

    三、实验体会

      微信、QQ、手机APP在进行网络连接时有何种安全措施?

      为了确保即时通讯的稳定性,采用了短链接(HTTP协议)和长链接(TCP协议)相结合的方式,分别应对状态协议和数据传输协议。短链接方式采用HTTP协议,主要用于用户登录信息验证、获取好友列表、用户头像、行为日志上报、刷新朋友圈等短期状态型的应用;长链接方式采用TCP协议,主要用于接收/发送文本消息、语音、图片、视频文件等传输过程需要保持连接状态的数据的传输。

      微信采用SYNC协议,是参考Activesync来实现的。SYNC是基于状态同步的协议,将信息的收发过程看作状态同步的过程。服务器每收到最新的消息或更新好友状态,都会将客户端与服务端消息进行同步。微信平台将交互模式简单化,只需要推送一个消息到达的通知,终端通过收到的通知进行信息同步。这种简化模式有利于微信在各种平台上的应用,通过状态差值同步数据的方式,获得最小的数据变更。同时,采用增量的传输模式得到最小的数据传输量。采用SYNC协议,可以确保信息是稳定传送、按序到达的。

  • 相关阅读:
    oracle权限配置
    oracle锁表处理
    小组成员
    个人项目 Individual Project
    Java单元测试框架 JUnit
    MyEclipse的快捷键大全(超级实用,方便)
    vs2008 连接 vss2005 出现 analyze utility 错误的解决方法
    EXTJS gridpanel 动态设置表头
    IE8不能上网的问题
    一些事件的评论
  • 原文地址:https://www.cnblogs.com/20201212ycy/p/16846180.html
Copyright © 2020-2023  润新知