安全传输平台项目——密钥协商服务器-密钥协商客户端
在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
10-安全传输平台项目-第05天(密钥协商服务器-密钥协商客户端)
目录:
一、复习
二、安全传输平台项目——密钥协商服务器-密钥协商客户端
1、密钥协商-物理组件集成
2、密钥协商-日志的使用
3、密钥协商客户端-模块划分
4、密钥协商客户端-框架实现
5、密钥协商客户端-Agree函数框架
6、密钥协商客户端-Agree函数实现
7、密钥协商客户端-Agree函数内存释放
8、密钥协商服务器-框架梳理
9、密钥协商服务器-业务逻辑实现
10、密钥协商服务器-Agree功能实现
11、总结
一、复习
1、线程传参
2、共享内存
二、安全传输平台项目——密钥协商服务器-密钥协商客户端
》密钥协商业务逻辑图:
1、密钥协商-物理组件集成
》创建相应的文件夹及文件准备
>mkdir secmng
>cd secmng
>mkdir inc
>mkdir lib
>mkdir src
通过远程软件,将库文件:libitcastsocket.so和libmessagereal.so拷贝到新创建的lib目录下;
把(keymnglog.c和myipc_shm.c)2个文件放入到src目录下,把(keymng_msg.h—统一报文编码解码,对应lib库libmessagereal.so、keymnglog.h—日志,对应inc的keymnglog.c、myipc_shm.h—统一共享内存,对应inc的myipc_shm.c、poolsocket.h—统一通信,对应lib库libitcastsocket.so)4个文件放入到inc目录下。
>vi keymnglog.c
#define _CRT_SECURE_NO_WARNINGS #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdarg.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include "keymnglog.h" #define ITCAST_DEBUG_FILE_ "keymngclient.log" #define ITCAST_MAX_STRING_LEN 10240 //Level类别 #define IC_NO_LOG_LEVEL 0 #define IC_DEBUG_LEVEL 1 #define IC_INFO_LEVEL 2 #define IC_WARNING_LEVEL 3 #define IC_ERROR_LEVEL 4 int KeyMngLevel[5] = {IC_NO_LOG_LEVEL, IC_DEBUG_LEVEL, IC_INFO_LEVEL, IC_WARNING_LEVEL, IC_ERROR_LEVEL}; //Level的名称 char ICLevelName[5][10] = {"NOLOG", "DEBUG", "INFO", "WARNING", "ERROR"}; static int ITCAST_Error_GetCurTime(char* strTime) { struct tm* tmTime = NULL; size_t timeLen = 0; time_t tTime = 0; tTime = time(NULL); tmTime = localtime(&tTime); //timeLen = strftime(strTime, 33, "%Y(Y)%m(M)%d(D)%H(H)%M(M)%S(S)", tmTime); timeLen = strftime(strTime, 33, "%Y.%m.%d %H:%M:%S", tmTime); return timeLen; } static int ITCAST_Error_OpenFile(int* pf) { char fileName[1024]; memset(fileName, 0, sizeof(fileName)); #ifdef WIN32 sprintf(fileName, "c:\\itcast\\%s",ITCAST_DEBUG_FILE_); #else sprintf(fileName, "%s/log/%s", getenv("HOME"), ITCAST_DEBUG_FILE_); #endif *pf = open(fileName, O_WRONLY|O_CREAT|O_APPEND, 0666); if(*pf < 0) { return -1; } return 0; } static void ITCAST_Error_Core(const char *file, int line, int level, int status, const char *fmt, va_list args) { char str[ITCAST_MAX_STRING_LEN]; int strLen = 0; char tmpStr[64]; int tmpStrLen = 0; int pf = 0; //初始化 memset(str, 0, ITCAST_MAX_STRING_LEN); memset(tmpStr, 0, 64); //加入LOG时间 tmpStrLen = ITCAST_Error_GetCurTime(tmpStr); tmpStrLen = sprintf(str, "[%s] ", tmpStr); strLen = tmpStrLen; //加入LOG等级 tmpStrLen = sprintf(str+strLen, "[%s] ", ICLevelName[level]); strLen += tmpStrLen; //加入LOG状态 if (status != 0) { tmpStrLen = sprintf(str+strLen, "[ERRNO is %d] ", status); } else { tmpStrLen = sprintf(str+strLen, "[SUCCESS] "); } strLen += tmpStrLen; //加入LOG信息 tmpStrLen = vsprintf(str+strLen, fmt, args); strLen += tmpStrLen; //加入LOG发生文件 tmpStrLen = sprintf(str+strLen, " [%s]", file); strLen += tmpStrLen; //加入LOG发生行数 tmpStrLen = sprintf(str+strLen, " [%d]\n", line); strLen += tmpStrLen; //打开LOG文件 if(ITCAST_Error_OpenFile(&pf)) { return ; } //写入LOG文件 write(pf, str, strLen); //IC_Log_Error_WriteFile(str); //关闭文件 close(pf); return ; } void KeyMng_Log(const char *file, int line, int level, int status, const char *fmt, ...) { va_list args; //判断是否需要写LOG // if(level!=IC_DEBUG_LEVEL && level!=IC_INFO_LEVEL && level!=IC_WARNING_LEVEL && level!=IC_ERROR_LEVEL) if(level == IC_NO_LOG_LEVEL) { return ; } //调用核心的写LOG函数 va_start(args, fmt); ITCAST_Error_Core(file, line, level, status, fmt, args); va_end(args); return ; }
>vi myipc_shm.c
#define _OS_LINUX_ #if defined _OS_LINUX_ #include <stdio.h> #include <errno.h> #include <unistd.h> #include <memory.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <sys/msg.h> #include "myipc_shm.h" #endif int shmflag = 0; int shmkey; //创建共享内存 若共享内存不存在,则创建 若存在使用原来的 int IPC_CreatShm(int key, int shmsize, int *shmhdl) { int tmpshmhdl = 0; int ret = 0; // 创建共享内存 // 若共享内存不存在则创建 // 若共享内存已存在使用原来的 tmpshmhdl = shmget(key, shmsize, IPC_CREAT|0666); if (tmpshmhdl == -1) //创建失败 { ret = MYIPC_ParamErr; printf("func shmget() err :%d ", ret); return ret; } *shmhdl = tmpshmhdl; return ret; } //打开共享内存 若共享内存不存在,返回错误 //参数 无意义 可填写0 int IPC_OpenShm(int key, int shmsize, int *shmhdl) { int tmpshmhdl = 0; int ret = 0; // 创建共享内存 // 若共享内存不存在则创建 // 若共享内存已存在使用原来的 tmpshmhdl = shmget(key, 0, 0); if (tmpshmhdl == -1) //打开失败 { ret = MYIPC_NotEXISTErr; //printf("func shmget() err :%d ", ret); return ret; } *shmhdl = tmpshmhdl; return ret; } /*********************************************************************** 功能描述: 创建共享内存 参数说明: shmname [in] 是共享内存名,系统中唯一标志 shmsize [in] 是要创建的共享内存的大小; shmhdl [out] 共享内存的句柄. 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_CreatShmBySeedName(const char *shmseedfile, int shmsize, int *shmhdl) { if(shmflag == 0) //判断接口中共享内存key是否已经存在 { shmkey = ftok(shmseedfile, 'c'); if (shmkey == -1) { perror("ftok"); return -1; } shmflag = 1; } //创建共享内存 *shmhdl = shmget(shmkey,shmsize,IPC_CREAT|0666); if (*shmhdl == -1) //创建失败 return -2; return 0; } /*********************************************************************** 功能描述: 关联共享内存 参数说明: shmhdl [in] 共享的句柄 mapaddr [out] 共享内存首地址 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_MapShm(int shmhdl, void **mapaddr) { void *tempptr = NULL; //连接共享内存 tempptr = (void *)shmat(shmhdl,0,SHM_RND); if ((int)tempptr == -1) //共享内存连接失败 return -1; *mapaddr = tempptr; //导出共享内存首指针 return 0; } /*********************************************************************** 功能描述: 取消共享内存关联 参数说明: unmapaddr [in] 共享内存首地址 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_UnMapShm(void *unmapaddr) { int rv; //取消连接共享内存 rv = shmdt((char *)unmapaddr); if (rv == -1) //取消连接失败 return -1; return 0; } /*********************************************************************** 功能描述: 删除共享内存 参数说明: shmhdl [in] 共享的句柄 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_DelShm(int shmhdl) { int rv; //删除共享内存 rv = shmctl(shmhdl,IPC_RMID,NULL); if(rv < 0) //删除共享内存失败 return -1; return 0; }
>vi keymng_msg.h
#ifndef _KEYMNG_MSG_H_ #define _KEYMNG_MSG_H_ #ifdef __cplusplus extern "C" { #endif #define KeyMng_ParamErr 200 //输入参数失败 #define KeyMng_TypeErr 201 //输入类型失败 #define KeyMng_MallocErr 202 //分配内存失败 #define KeyMng_NEWorUPDATE 1 //1 密钥协商 #define KeyMng_Check 2 //2 密钥校验 #define KeyMng_Revoke 3 //3 密钥注销 #define ID_MsgKey_Teacher 80 typedef struct _Teacher { char name[64]; int age; char *p; int plen; }Teacher; //密钥请求报文 --- 结构体 #define ID_MsgKey_Req 60 typedef struct _MsgKey_Req { //1 密钥协商 //2 密钥校验; //3 密钥注销 int cmdType; //报文命令码 char clientId[12]; //客户端编号 char AuthCode[16]; //认证码 char serverId[12]; //服务器端I编号 char r1[64]; //客户端随机数 }MsgKey_Req; //密钥应答报文 --- 结构体 #define ID_MsgKey_Res 61 typedef struct _MsgKey_Res { int rv; //返回值 char clientId[12]; //客户端编号 char serverId[12]; //服务器编号 unsigned char r2[64]; //服务器端随机数 int seckeyid; //对称密钥编号 //modfy 2015.07.20 }MsgKey_Res; /* pstruct : 输入的报文数据 ; (指向相应结构体的指针) type : 输入的类型标识(函数内部通过type 得到 pstruct 所指向的报文类型) poutData: 输出的编码后的报文 ; outlen : 输出的数据长度; */ int MsgEncode( void *pStruct , /*in*/ int type, unsigned char **outData, /*out*/ int *outLen ); /* inData : 输入的编码后的数据; inLen : 输入的数据长度 ; pstruct : 输出的解码后的数据; (其空间是在内部开辟的,也需要用内部定义的free函数进行释放) type : 结构的类型标识(返回类型标识,使得调用者通过flag进行判断,将pstruct 转换为相应的结构) */ int MsgDecode( unsigned char *inData,/*in*/ int inLen, void **pStruct /*out*/, int *type /*out*/); /* 释放 MsgEncode( )函数中的outData; 方法:MsgMemFree((void **)outData, 0); 释放MsgDecode( )函数中的pstruct结构体,MsgMemFree((void **)outData, type); type : 输入参数,便于函数判断调用哪个结构体的free函数 */ int MsgMemFree(void **point, int type); #ifdef __cplusplus } #endif #endif
>vi keymnglog.h
//keymnglog.h 日志头文件 // keymnglog.h #ifndef _KEYMNG_LOG_H_ #define _KEYMNG_LOG_H_ /************************************************************************/ /* const char *file:文件名称 int line:文件行号 int level:错误级别 0 -- 没有日志 1 -- debug级别 2 -- info级别 3 -- warning级别 4 -- err级别 int status:错误码 const char *fmt:可变参数 */ /************************************************************************/ //实际使用的Level extern int KeyMngLevel[5]; void KeyMng_Log(const char *file, int line, int level, int status, const char *fmt, ...); #endif
>vi myipc_shm.h
// myipc_shm.h #ifndef _WBM_MY_SHM_H_ #define _WBM_MY_SHM_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef __cplusplus extern "C" { #endif //共享内存错误码 #define MYIPC_OK 0 //正确 #define MYIPC_ParamErr 301 //输入参数失败 #define MYIPC_NotEXISTErr 302 //共享内存不存在错误 #define MYIPC_CreateErr 303 //创建共享内存错误 //创建共享内存 若共享内存不存在,则创建 int IPC_CreatShm(int key, int shmsize, int *shmhdl); //打开共享内存 若共享内存不存在,返回错误 int IPC_OpenShm(int key, int shmsize, int *shmhdl); /*********************************************************************** 功能描述: 关联共享内存 参数说明: shmhdl [in] 共享的句柄 mapaddr [out] 共享内存首地址 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_MapShm(int shmhdl, void **mapaddr); /*********************************************************************** 功能描述: 取消共享内存关联 参数说明: unmapaddr [in] 共享内存首地址 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_UnMapShm(void *unmapaddr); /*********************************************************************** 功能描述: 删除共享内存 参数说明: shmhdl [in] 共享的句柄 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_DelShm(int shmhdl); /*********************************************************************** 功能描述: 创建共享内存 通过种子文件 参数说明: shmname [in] 是共享内存名,系统中唯一标志 shmsize [in] 是要创建的共享内存的大小; shmhdl [out] 共享内存的句柄. 返回值: 返回0函数执行成功;非0返回错误码 ************************************************************************/ int IPC_CreatShmBySeedName(const char *shmname, int shmsize, int *shmhdl); #ifdef __cplusplus } #endif #endif
>vi poolsocket.h
#ifndef _poolsocket_H_ #define _poolsocket_H_ #ifdef __cplusplus extern 'C' { #endif //错误码定义 #define Sck_Ok 0 #define Sck_BaseErr 3000 #define Sck_ErrParam (Sck_BaseErr+1) #define Sck_ErrTimeOut (Sck_BaseErr+2) #define Sck_ErrPeerClosed (Sck_BaseErr+3) #define Sck_ErrMalloc (Sck_BaseErr+4) #define Sck_Err_Pool_CreateConn (Sck_BaseErr+20) //创建连接池 (没有达到最大连接数) #define Sck_Err_Pool_terminated (Sck_BaseErr+21) //已终止 #define Sck_Err_Pool_GetConn_ValidIsZero (Sck_BaseErr+22) //有效连接数是零 #define Sck_Err_Pool_HaveExist (Sck_BaseErr+22) //连接已经在池中 #define Sck_Err_Pool_ValidBounds (Sck_BaseErr+22) //有效连接数目超过了最大连接数 //客户端 初始化 int sckClient_init(); //客户端 连接服务器 int sckClient_connect(char *ip, int port, int connecttime, int *connfd); //客户端 关闭和服务端的连接 int sckClient_closeconn(int connfd); //客户端 发送报文 int sckClient_send(int connfd, int sendtime, unsigned char *data, int datalen); //客户端 接受报文 int sckClient_rev(int connfd, int revtime, unsigned char **out, int *outlen); //1 //客户端 释放 int sckClient_destroy(); //释放内存 int sck_FreeMem(void **buf); typedef struct _SCKClitPoolParam { char serverip[64]; int serverport; int bounds; //池容量 int connecttime; int sendtime; int revtime; }SCKClitPoolParam; //客户端 socket池初始化 int sckCltPool_init(void **handle, SCKClitPoolParam *param); //ip port 数量 //客户端 socket池 获取一条连接 int sckCltPool_getConnet(void *handle, int *connfd); //客户端 socket池 发送数据 int sckCltPool_send(void *handle, int connfd, unsigned char *data, int datalen); //客户端 socket池 接受数据 int sckCltPool_rev(void *handle, int connfd, unsigned char **out, int *outlen); //1 //客户端 socket池 把连接放回 socket池中 int sckCltPool_putConnet(void *handle, int connfd, int validFlag); //0正常 1 //客户端 socket池 销毁连接 int sckCltPool_destroy(void *handle); //服务器端初始化 int sckServer_init(int port, int *listenfd); int sckServer_accept(int listenfd, int timeout, int *connfd); //服务器端发送报文 int sckServer_send(int connfd, int timeout, unsigned char *data, int datalen); //服务器端端接受报文 int sckServer_rev(int connfd, int timeout, unsigned char **out, int *outlen); //1 int sckServer_close(int connfd); //服务器端环境释放 int sckServer_destroy(); #ifdef __cpluspluse } #endif #endif
2、密钥协商-日志的使用
>cd src
>touch keymngclient.c
>touch keymngserver.c
>vi keymngclient.c
#include "keymnglog.h" int main(void) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[0], 0, "%s", "00000000000000"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[1], 1, "%s", "11111111111111"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[2], 2, "%s", "22222222222222"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[3], 3, "%s", "33333333333333"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], 4, "%s", "44444444444444"); return 0; }
>gcc keymngclient.c keymnglog.c -o keymngclient -I ../inc
>./keymngclient
打开另一个终端,然后在家目录的log目录下查看日志
注意:0的时候没有日志,所以查看的时候只有4行。
3、密钥协商客户端-模块划分
》密钥协商客户端: keymngclient.c
显示菜单。
接收用户选择。 num。
客户端信息初始化。
switch(num) {
case 1协商:
密钥协商。 建立连接、封装req结构体、编码、发送、接收、解码、生成密钥、写共享内存。
_Agree();
case 2校验:
密钥校验。 建立连接、封装req结构体、编码、发送、接收、解码、展示结果给用户。
_Check();
case 3查看:
密钥查看。 建立连接、封装req结构体、编码、发送、接收、解码、展示密钥相关信息给用户。
_View();
。。。。
}
将结果展示给用户。
》模块划分:
业务逻辑:
keymngclient.c
业务功能:
keymngclientop.c --> keymngclientop.h
实现 客户端信息初始化。 客户端信息初始化声明。
实现 客户端密钥协商。 。。。。
实现 客户端密钥校验。
struct clientInfo { serverIp, serverPort, clientID, serverID, Autocode, shmkey, shmid, maxnode }
int keymng_initInfo(struct clientInfo *pInfo);传出参数
int keymng_Agree(struct clientInfo *pInfo)
int keymng_Check(struct clientInfo *pInfo);
int keymng_Revoke(struct clientInfo *pInfo);
====================================================================
》密钥协商服务器:
keymngserverop.c keymngserverop.h 功能实现
实现 服务器信息初始化。 服务器信息初始化声明。
实现 服务器密钥协商。 。。。。
实现 服务器密钥校验。
实现 服务器密钥注销。
4、密钥协商客户端-框架实现
》文件准备:
// keymngclientop.h #ifndef _KEYMNG_CLIENTOP_H_ #define _KEYMNG_CLIENTOP_H_ #ifdef __cplusplus extern "C" { #endif #define MngClt_OK 0 //正确 #define MngClt_ParamErr 301 //输入参数失败 #define MngClt_NoNetPointErr 302 //共享内存中,没有找到网点信息 #define MngClt_NodeMaxCount 303 //共享内存中,超过最大网点 typedef struct _MngClient_Info { char clientId[12]; //客户端编号 char AuthCode[16]; //认证码 char serverId[12]; //服务器端编号 char serverip[32]; int serverport; int maxnode; //最大网点数 客户端默认1个 int shmkey; //共享内存keyid 创建共享内存时使用 int shmhdl; //共享内存句柄 }MngClient_Info; //初始化客户端 全局变量 int MngClient_InitInfo(MngClient_Info *pCltInfo); int MngClient_Quit(MngClient_Info *pCltInfo); int MngClient_Agree(MngClient_Info *pCltInfo); int MngClient_Check(MngClient_Info *pCltInfo); int MngClient_Revoke(MngClient_Info *pCltInfo); int MngClient_view(MngClient_Info *pCltInfo); #ifdef __cplusplus } #endif #endif
将keymngclientop.h放入ins目录下,然后在src新建keymngclientop.c,进行开发
>touch keymngclientop.c
>vi keymngclientop.c
#include <stdio.h> #include <stdlib.h> #include "keymngclientop.h" int MngClient_InitInfo(MngClient_Info *pCltInfo) { strcpy(pCltInfo->clientId, "1111"); strcpy(pCltInfo->AuthCode, "1111"); strcpy(pCltInfo->serverId, "0001"); strcpy(pCltInfo->serverip, "127.0.0.1"); pCltInfo->serverport = 8001; pCltInfo->maxnode = 1; pCltInfo->shmkey = 0x0011; pCltInfo->shmhdl = 0; return 0; } int MngClient_Agree(MngClient_Info *pCltInfo) { return 0; }
5、密钥协商客户端-Agree函数框架
>keymngclient.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "keymngclientop.h" #include "keymng_msg.h" #include "keymnglog.h" int main111(void) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[0], 0, "%s", "00000000000000"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[1], 1, "%s", "11111111111111"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[2], 2, "%s", "22222222222222"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[3], 3, "%s", "33333333333333"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], 4, "%s", "44444444444444"); return 0; } int Usage() { int nSel = -1; system("clear"); printf("\n /*************************************************************/"); printf("\n /*************************************************************/"); printf("\n /* 1.密钥协商 */"); printf("\n /* 2.密钥校验 */"); printf("\n /* 3.密钥注销 */"); printf("\n /* 4.密钥查看 */"); printf("\n /* 0.退出系统 */"); printf("\n /*************************************************************/"); printf("\n /*************************************************************/"); printf("\n\n 选择:"); scanf("%d", &nSel); while(getchar() != '\n'); //把应用程序io缓冲器的所有的数据 都读走,避免影响下一次 输入 return nSel; } int main() { int ret = 0; int nSel = 0; MngClient_Info mngClientInfo; memset(&mngClientInfo, 0, sizeof(MngClient_Info)); // 初始化客户端结构体信息 ret = MngClient_InitInfo(&mngClientInfo); if (ret != 0) { printf("func MngClient_InitInfo() err:%d \n ", ret); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MngClient_InitInfo() err:%d", ret); } while (1) { // 显示菜单 接收用户选择 nSel = Usage(); switch (nSel) { case KeyMng_NEWorUPDATE: //密钥协商 ret = MngClient_Agree(&mngClientInfo); break; case KeyMng_Check: //ret = MngClient_Check(&mngClientInfo); break; case KeyMng_Revoke: //密钥注销 break; case 0: //退出 return 0; default : printf("选项不支持\n"); break; } // 结果展示给用户。 if (ret) { printf("\n!!!!!!!!!!!!!!!!!!!!ERROR!!!!!!!!!!!!!!!!!!!!"); printf("\n错误码是:%x\n", ret); } else { printf("\n!!!!!!!!!!!!!!!!!!!SUCCESS!!!!!!!!!!!!!!!!!!!!\n"); } getchar(); } return 0; }
>keymngclientop.c
int MngClient_Agree(MngClient_Info *pCltInfo) { //组织密钥请求结构体 req //编码密钥请求结构体 req --> TLV //初始化连接 --> listenfd //建立连接 --> connfd //发送请求报文 --> TLV send //接收应答报文 --> 服务器TLV res //解析应答报文 --> TLV --> Struct --> rv / r2 //生成密钥 --> r1 r2 算法 --> 密钥 //写共享内存。--> 存储 return 0; }
>vi keymngclientop.c
#include <stdio.h> #include <stdlib.h> #include "keymngclientop.h" int MngClient_InitInfo(MngClient_Info *pCltInfo) { strcpy(pCltInfo->clientId, "1111"); strcpy(pCltInfo->AuthCode, "1111"); strcpy(pCltInfo->serverId, "0001"); strcpy(pCltInfo->serverip, "127.0.0.1"); pCltInfo->serverport = 8001; pCltInfo->maxnode = 1; pCltInfo->shmkey = 0x0011; pCltInfo->shmhdl = 0; return 0; } int MngClient_Agree(MngClient_Info *pCltInfo) { //组织密钥请求结构体 //编码密钥请求结构体 //初始化连接 //建立连接 //发送请求报文 //接收应答报文 //解析应答报文 //生成密钥 //写共享内存。 return 0; }
6、密钥协商客户端-Agree函数实现
>keymngclient.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "keymngclientop.h" #include "keymng_msg.h" #include "keymnglog.h" int main111(void) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[0], 0, "%s", "00000000000000"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[1], 1, "%s", "11111111111111"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[2], 2, "%s", "22222222222222"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[3], 3, "%s", "33333333333333"); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], 4, "%s", "44444444444444"); return 0; } int Usage() { int nSel = -1; system("clear"); printf("\n /*************************************************************/"); printf("\n /*************************************************************/"); printf("\n /* 1.密钥协商 */"); printf("\n /* 2.密钥校验 */"); printf("\n /* 3.密钥注销 */"); printf("\n /* 4.密钥查看 */"); printf("\n /* 0.退出系统 */"); printf("\n /*************************************************************/"); printf("\n /*************************************************************/"); printf("\n\n 选择:"); scanf("%d", &nSel); while(getchar() != '\n'); //把应用程序io缓冲器的所有的数据 都读走,避免影响下一次 输入 return nSel; } int main() { int ret = 0; int nSel = 0; MngClient_Info mngClientInfo; memset(&mngClientInfo, 0, sizeof(MngClient_Info)); // 初始化客户端结构体信息 ret = MngClient_InitInfo(&mngClientInfo); if (ret != 0) { printf("func MngClient_InitInfo() err:%d \n ", ret); KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MngClient_InitInfo() err:%d", ret); } while (1) { // 显示菜单 接收用户选择 nSel = Usage(); switch (nSel) { case KeyMng_NEWorUPDATE: //密钥协商 ret = MngClient_Agree(&mngClientInfo); break; case KeyMng_Check: //ret = MngClient_Check(&mngClientInfo); break; case KeyMng_Revoke: //密钥注销 break; case 0: //退出 return 0; default : printf("选项不支持\n"); break; } // 结果展示给用户。 if (ret) { printf("\n!!!!!!!!!!!!!!!!!!!!ERROR!!!!!!!!!!!!!!!!!!!!"); printf("\n错误码是:%x\n", ret); } else { printf("\n!!!!!!!!!!!!!!!!!!!SUCCESS!!!!!!!!!!!!!!!!!!!!\n"); } getchar(); } return 0; }
>keymngclientop.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "keymnglog.h" #include "poolsocket.h" #include "keymng_msg.h" #include "keymngclientop.h" int MngClient_InitInfo(MngClient_Info *pCltInfo) { strcpy(pCltInfo->clientId, "1111"); strcpy(pCltInfo->AuthCode, "1111"); strcpy(pCltInfo->serverId, "0001"); strcpy(pCltInfo->serverip, "127.0.0.1"); pCltInfo->serverport = 8001; pCltInfo->maxnode = 1; pCltInfo->shmkey = 0x0011; pCltInfo->shmhdl = 0; return 0; } int MngClient_Agree(MngClient_Info *pCltInfo) { int i = 0; int ret = 0; int time = 3; int connfd = -1; // 存放编码 TLV 完成的 req unsigned char *msgKey_Req_Data = NULL; int msgKey_Req_DataLen = 0; // 存放编码 TLV 完成的 res unsigned char *msgKey_Res_Data = NULL; int msgKey_Res_DataLen = 0; MsgKey_Res *pStruct_Res = NULL; int iType = 0; // 初始化密钥请求结构体 MsgKey_Req msgKey_req; msgKey_req.cmdType = KeyMng_NEWorUPDATE; strcpy(msgKey_req.clientId, pCltInfo->clientId); strcpy(msgKey_req.AuthCode, pCltInfo->AuthCode); strcpy(msgKey_req.serverId, pCltInfo->serverId); // 产生随机数 abcdefg for (i = 0; i < 64; i++) { msgKey_req.r1[i] = 'a' + i; } // 编码密钥请求 结构体 req ret = MsgEncode(&msgKey_req, ID_MsgKey_Req, &msgKey_Req_Data, &msgKey_Req_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MsgEncode() err:%d", ret); return 0; } // 初始化建立连接函数 ret = sckClient_init(); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_init() err:%d", ret); return 0; } // 创建连接。 ret = sckClient_connect(pCltInfo->serverip, pCltInfo->serverport, time, &connfd); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_connect() err:%d", ret); return 0; } // 发送数据 ret = sckClient_send(connfd, time, msgKey_Req_Data, msgKey_Req_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_send() err:%d", ret); return 0; } // ---- 等待服务器回发数据 // 接收数据 ret = sckClient_rev(connfd, time, &msgKey_Res_Data, &msgKey_Res_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_rev() err:%d", ret); return 0; } // 解码密钥应答 结构体 res ---> rv r2 ret = MsgDecode(msgKey_Res_Data, msgKey_Res_DataLen, (void **)&pStruct_Res, &iType); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MsgDecode() err:%d", ret); return 0; } if (pStruct_Res->rv != 0) { ret = -1; return 0; } else if (pStruct_Res->rv == 0) { ret = 0; printf("---当前生成的密钥编号为:%d\n", pStruct_Res->seckeyid); return 0; } // --利用 r1 r2 生成密钥 // --写入共享内存。 return ret; }
注意:生成密钥 --> r1 r2 算法 --> 密钥 和 写共享内存。--> 存储 暂不实现。
7、密钥协商客户端-Agree函数内存释放
>free——MsgMemFree
>keymngclientop.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "keymnglog.h" #include "poolsocket.h" #include "keymng_msg.h" #include "keymngclientop.h" int MngClient_InitInfo(MngClient_Info *pCltInfo) { strcpy(pCltInfo->clientId, "1111"); strcpy(pCltInfo->AuthCode, "1111"); strcpy(pCltInfo->serverId, "0001"); strcpy(pCltInfo->serverip, "127.0.0.1"); pCltInfo->serverport = 8001; pCltInfo->maxnode = 1; pCltInfo->shmkey = 0x0011; pCltInfo->shmhdl = 0; return 0; } int MngClient_Agree(MngClient_Info *pCltInfo) { int i = 0; int ret = 0; int time = 3; int connfd = -1; // 存放编码 TLV 完成的 req unsigned char *msgKey_Req_Data = NULL; int msgKey_Req_DataLen = 0; // 存放编码 TLV 完成的 res unsigned char *msgKey_Res_Data = NULL; int msgKey_Res_DataLen = 0; MsgKey_Res *pStruct_Res = NULL; int iType = 0; // 初始化密钥请求结构体 MsgKey_Req msgKey_req; msgKey_req.cmdType = KeyMng_NEWorUPDATE; strcpy(msgKey_req.clientId, pCltInfo->clientId); strcpy(msgKey_req.AuthCode, pCltInfo->AuthCode); strcpy(msgKey_req.serverId, pCltInfo->serverId); // 产生随机数 abcdefg for (i = 0; i < 64; i++) { msgKey_req.r1[i] = 'a' + i; } // 编码密钥请求 结构体 req ret = MsgEncode(&msgKey_req, ID_MsgKey_Req, &msgKey_Req_Data, &msgKey_Req_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MsgEncode() err:%d", ret); goto END; } // 初始化建立连接函数 ret = sckClient_init(); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_init() err:%d", ret); goto END; } // 创建连接。 ret = sckClient_connect(pCltInfo->serverip, pCltInfo->serverport, time, &connfd); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_connect() err:%d", ret); goto END; } // 发送数据 ret = sckClient_send(connfd, time, msgKey_Req_Data, msgKey_Req_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_send() err:%d", ret); goto END; } // ---- 等待服务器回发数据 // 接收数据 ret = sckClient_rev(connfd, time, &msgKey_Res_Data, &msgKey_Res_DataLen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func sckClient_rev() err:%d", ret); goto END; } // 解码密钥应答 结构体 res ---> rv r2 ret = MsgDecode(msgKey_Res_Data, msgKey_Res_DataLen, (void **)&pStruct_Res, &iType); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "func MsgDecode() err:%d", ret); goto END; } if (pStruct_Res->rv != 0) { ret = -1; goto END; } else if (pStruct_Res->rv == 0) { ret = 0; printf("---当前生成的密钥编号为:%d\n", pStruct_Res->seckeyid); goto END; } // --利用 r1 r2 生成密钥 // --写入共享内存。 END: if (msgKey_Req_Data != NULL) MsgMemFree((void **)&msgKey_Req_Data, 0); if (msgKey_Res_Data != NULL) MsgMemFree((void **)&msgKey_Res_Data, 0); if (pStruct_Res != NULL) MsgMemFree((void **)&pStruct_Res, iType); return ret; }
8、密钥协商服务器-框架梳理
》密钥协商服务器:
void *callback(void *arg) { // 接收客户端 密钥请求报文 --- TLV req // 解码客户端 密钥请求报文 ---> cmdType switch(cmdType) { case 密钥协商: mngServer_Agree(); break; case 密钥校验: mngServer_Check(); break; case 密钥注销: mngServer_Revoke();
break; default: break; } // 发送应答报文 } keymngserver.c -------业务逻辑 { // 服务器信息初始化。 // 监听客户端连接请求 while(1) { // 启动线程 与客户端 进行通信 fd pthread_create(, (void *)fd); } }
注意:服务器与客户端区别的主要原因是:服务器必须接收数据包解码以后才知道客户端想做什么,而客户端在发送数据之前就清楚自己要干什么!
服务器的发送应答报文放到Agree函数外边,所以服务器的Agree函数的接口与客户端Agree函数接口不同。(两种都可以,根据需求都可以做。)
keymngserverop.c keymngserverop.h 功能实现
实现 服务器信息初始化。 服务器信息初始化声明。
实现 服务器密钥协商。 。。。。
实现 服务器密钥校验。
实现 服务器密钥注销。
struct serverInfo {serverIp, serverPort, serverID, shmkey, shmid, maxnode, dbuser, dbpasswd, dbname, maxnum} 不变
int MngServer_Agree(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen); { // 生成随机数 r2 // 结合 r1 r2 生成密钥 ---> 成功、失败 rv // 组织 应答结构体 res : rv r2 clientId serverId seckeyid // 写共享内存 // 写数据库 // 编码应答报文 传出 }
9、密钥协商服务器-业务逻辑实现
>keymngserverop.h
// keymngserverop.h #ifndef _KEYMNG_ServerOp_H_ #define _KEYMNG_ServerOp_H_ #include "keymng_msg.h" #ifdef __cplusplus extern "C" { #endif //keymngserver 错误码 #define MngSvr_OK 0 //正确 #define MngSvr_ParamErr 301 //输入参数失败 #define MngSvr_NoNetPointErr 302 //共享内存中,没有找到网点信息 #define MngSvr_NodeMaxCount 303 //共享内存中,超过最大网点 #define MngSvr_CheckErr 304 //共享内存中,超过最大网点 typedef struct _MngServer_Info { char serverId[12]; //服务器端编号 //数据库连接池句柄 char dbuse[24]; //数据库用户名 char dbpasswd[24]; //数据库密码 char dbsid[24]; //数据库sid int dbpoolnum; //数据库池 连接数 char serverip[24]; int serverport; //共享内存配置信息 int maxnode; //最大网点树 客户端默认1个 int shmkey; //共享内存keyid 创建共享内存时使用 int shmhdl; //共享内存句柄 }MngServer_Info; //初始化服务器 全局变量 int MngServer_InitInfo(MngServer_Info *svrInfo); int MngServer_Quit(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen); //服务端 密钥协商应答流程 int MngServer_Agree(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen); //int keymngsever_agree(MngServer_Info *pServferInfo, MsgKey_Req *pMsgKeyReq , unsigned char **pMsgKeyResData, int *pMsgKeyResDataLen) int MngServer_Check(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen); int MngServer_Revoke(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen); int MngServer_view(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen); #ifdef __cplusplus } #endif #endif
>keymngserverop.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "keymngserverop.h" #include "keymng_msg.h" #include "keymnglog.h" int MngServer_InitInfo(MngServer_Info *svrInfo) { strcpy(svrInfo->serverId, "0001"); strcpy(svrInfo->dbuse, "SECMNG"); strcpy(svrInfo->dbpasswd, "SECMNG"); strcpy(svrInfo->dbsid, "orcl"); svrInfo->dbpoolnum = 8; strcpy(svrInfo->serverip, "127.0.0.1"); svrInfo->serverport = 8001; svrInfo->maxnode = 10; svrInfo->shmkey = 0x0001; svrInfo->shmhdl = 0; return 0; } int MngServer_Agree(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen) { return 0; }
>keymngserver.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include "poolsocket.h" #include "keymngserverop.h" #include "keymng_msg.h" #include "keymnglog.h" MngServer_Info serverInfo; void *start_routine(void * arg) { int ret; int timeout = 3; int connfd = (int)arg; unsigned char *out = NULL; int outlen = 0; MsgKey_Req *pStruct_req = NULL; int iType = 0; unsigned char *res_outData = NULL; int res_outDataLen = 0; while (1) { //服务器端端接受报文 ret = sckServer_rev(connfd, timeout, &out, &outlen); if (ret == Sck_ErrPeerClosed) { // 检测到 对端关闭,关闭本端。 printf("----------------ErrPeerClosed 关闭服务器\n"); break; } else if (ret == Sck_ErrTimeOut) { printf("---服务器检测到客户端发送数据 超时 \n"); continue; } else if (ret != 0) { printf("未知错误\n"); break; } // 解码客户端 密钥请求报文 ---> cmdType ret = MsgDecode(out, outlen, (void **)&pStruct_req, &iType); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "MsgDecode() err:%d", ret); return ret; } switch(pStruct_req->cmdType) { case KeyMng_NEWorUPDATE: ret = MngServer_Agree(&serverInfo, pStruct_req, &res_outData, &res_outDataLen); /* case 密钥校验: mngServer_Agree(); case 密钥注销: mngServer_Agree(); */ default: break; } if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "MngServer_Agree() err:%d", ret); } //服务器端发送报文 ret = sckServer_send(connfd, timeout, res_outData, res_outDataLen); if (ret == Sck_ErrPeerClosed) { // 检测到 对端关闭,关闭本端。 printf("---ErrPeerClosed \n"); break; } else if (ret == Sck_ErrTimeOut) { printf("---服务器检测到本端发送数据 超时 \n"); continue; } else if (ret != 0) { printf("未知错误\n"); break; } } sckServer_close(connfd); return NULL; } int main(void) { int listenfd; int ret = 0; int timeout = 3; int connfd = -1; pthread_t pid; // 服务器信息初始化。 ret = MngServer_InitInfo(&serverInfo); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "MngServer_InitInfo() err:%d", ret); return ret; } //服务器端初始化 ret = sckServer_init(serverInfo.serverport, &listenfd); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "sckServer_init() err:%d", ret); return ret; } while (1) { ret = sckServer_accept(listenfd, timeout, &connfd); if (ret == Sck_ErrTimeOut){ KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[2], ret, "---等待客户端连接超时---"); continue; } else if(ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "sckServer_accept() err:%d", ret); return ret; } ret = pthread_create(&pid, NULL, start_routine, (void *)connfd); } //服务器端环境释放 sckServer_destroy(); return 0; }
>报错1:程序中有游离的“\357”
>报错2:[ERRNO is 98]func bind() err
端口占用问题;>ps aux | grep keymngserver查看pid;然后kill pid
>vi makefile
.PHONY:clean all WORKDIR=. VPATH = ./src CC=gcc CFLGS= -Wall -g -I$(WORKDIR)/inc/ LIBFLAG = -L$(HOME)/lib BIN = keymngclient keymngserver all:$(BIN) #myipc_shm.o keymng_shmop.o keymngclient:keymngclient.o keymnglog.o keymngclientop.o $(CC) $(LIBFLAG) -lpthread -litcastsocket -lmessagereal $^ -o $@ #myipc_shm.o keymng_shmop.o keymng_dbop.o -lclntsh -licdbapi keymngserver:keymngserver.o keymngserverop.o keymnglog.o $(CC) $(LIBFLAG) $^ -o $@ -lpthread -litcastsocket -lmessagereal #testdbapi:testdbapi.o # $(CC) $(LIBFLAG) $^ -o $@ -lpthread -lclntsh -licdbapi %.o:%.c $(CC) $(CFLGS) -c $< -o $@ clean: rm -f *.o $(BIN)
>make
>./keymngclient
打开另一个终端,执行>./keymngserver,
原终端情况:
服务器端情况:
10、密钥协商服务器-Agree功能实现
>vi keymngserver.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "keymngserverop.h" #include "keymng_msg.h" #include "keymnglog.h" static int seckeyid = 100; int MngServer_InitInfo(MngServer_Info *svrInfo) { strcpy(svrInfo->serverId, "0001"); strcpy(svrInfo->dbuse, "SECMNG"); strcpy(svrInfo->dbpasswd, "SECMNG"); strcpy(svrInfo->dbsid, "orcl"); svrInfo->dbpoolnum = 8; strcpy(svrInfo->serverip, "127.0.0.1"); svrInfo->serverport = 8001; svrInfo->maxnode = 10; svrInfo->shmkey = 0x0001; svrInfo->shmhdl = 0; return 0; } int MngServer_Agree(MngServer_Info *svrInfo, MsgKey_Req *msgkeyReq, unsigned char **outData, int *datalen) { int ret = 0; int i = 0; MsgKey_Res msgKey_Res; // --结合 r1 r2 生成密钥 ---> 成功、失败 rv if (strcmp(svrInfo->serverId, msgkeyReq->serverId) != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "客户端访问了错误的服务器"); return -1; } // 组织 应答结构体 res : rv r2 clientId serverId seckeyid msgKey_Res.rv = 0; //0 成功 1 失败。 strcpy(msgKey_Res.clientId, msgkeyReq->clientId); strcpy(msgKey_Res.serverId, msgkeyReq->serverId); // 生成随机数 r2 for (i = 0; i < 64; i++) { msgKey_Res.r2[i] = 'a' + i; // } msgKey_Res.seckeyid = seckeyid++; // --写共享内存 // --写数据库 // 编码应答报文 传出 ret = MsgEncode(&msgKey_Res, ID_MsgKey_Res, outData, datalen); if (ret != 0) { KeyMng_Log(__FILE__, __LINE__, KeyMngLevel[4], ret, "serverAgree MsgEncode() err:%d", ret); return ret; } return 0; }
注意:结合 r1 r2 生成密钥、写共享内存、写数据库 暂不实现。
>make
>./keymngclient
打开另一个终端,执行>./keymngserver,分别查看终端执行情况。
客户端情况:(输入:1)
点击“Enter”后,再次输入:1
服务器端情况:
11、总结
》客户端:keymngclient.c—负责业务逻辑;keymngclientop.c—负责功能实现
》服务器:keymngserver.c—负责业务逻辑;keymngserverop.c—负责功能实现
注意:服务器与客户端区别的主要原因是:服务器必须接收数据包解码以后才知道客户端想做什么,而客户端在发送数据之前就清楚自己要干什么!
在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。
posted on 2020-07-28 13:45 Alliswell_WP 阅读(832) 评论(0) 编辑 收藏 举报