数据传输项目(四)

1、共享内存类图

 在使用共享内存时,如果想记录共享内存的相关信息,可以在共享内存的头部来记录信息,比如设计一个结构体:类似

struct head{

    int total;
    int usuNum;
}

2、生成随机字符串

#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<time.h>
using m=namespace std;
void getRandString(char *pRandBuf,int len){
    srand(time(NULL));//最好放在main函数里
    int flag;
    char buf[]="!@#$%&^*()-=~+";

    for(int i=0;i<len-1;++i){
        flag=rand()%4;
        switch(flag){
            case 0:
                    pRandBuf[i]=rand()%10+'0';
                    break;
            case 1:
                    pRandBuf[i]=rand()%26+'A';
                    break;
            case 2:
                    pRandBuf[i]=rand()%26+'a';
                    break;
            case 3:
                    pRandBuf[i]=buf[rand()%strlen(buf)];
                    break;
            default:
                    break;
}
}
}

密钥协商流程:

1、客户端生成随机数r1,同时使用openssl中哈希函数对r1进行哈希运算,得到一个哈希值

2、将要发送的数据进行编码

3、发送数据给服务端

4、服务端收到请求数据后先解码

5、服务端根据客户端ID+服务端ID查询数据库,校验客户端是否合法,如果不合法就拒绝服务

6、服务端校验r1消息验证码:首先用和客户端相同的算法生成哈希值,然后将哈希值与接收到的哈希值作比较,如果不一样就拒绝服务;如果一致就继续后续操作

7、服务端生成随机数r2

8、服务端将r1和r2进行拼接,然后使用与客户端相同的哈希算法,得到一个哈希值,这个哈希值就当作新的秘钥seckey2;

9、将密钥信息写入共享内存和数据库中

10、服务端发送应答信息

11、客户端等待接收服务端应答

12、对接收到的数据进行解码

13、判断rv值,若为-1生成密钥失败,

14、如果rv为0,则生成成功,收到服务端生成的随机字符串r2,将r1和r2拼接,然后进行哈希运算,得到一个新的秘钥seckey1;

15、客户端将密钥信息写入共享内存

秘钥校验:

1、客户端将秘钥进行哈希运算,得到一个哈希值

2、将哈希值发送给服务端

3、服务端收到哈希值,并且自己也生成一个哈希值

4、服务端将两个哈希值进行比较,相同则协商成功,失败则重新协商

秘钥注销:

1、将clientID/serverID/秘钥ID发送给服务端

2、服务端收到请求后将共享内存的状态修改为不可用状态,将数据库中密钥的使用状态修改为不可用状态

秘钥查看:

1、根据日期

2、根据秘钥ID

// 客户端给服务器发送数据的时候用到的数据结构
struct RequestMsg
{
    int cmdType; 	   //0-秘钥协商 1-秘钥校验 2-秘钥注销 3-秘钥查看
    char clientId[12]; //客户端ID, 是唯一的, 不同的客户端有不同的ID
    char authCode[65]; //消息验证码, 对r1进行验证
    char serverId[12]; //服务端ID
    char r1[64];       //客户端生成的随机字符串
};


// 服务器给客户端回复的时候用的到结构
struct RespondMsg
{
    int rv; 		   //0-表示成功 -1-表示失败
    char clientId[12]; //客户端ID
    char serverId[12]; //服务端ID 
    char r2[64]; 	   //秘钥协商: 随机字符串, 秘钥查看: 秘钥  秘钥校验和注销:可不写 
    int seckeyid; 	   //秘钥ID :服务端生成的 
};

密钥协商客户端开发流程:

1、while(1){
读取用户输入:
c=getchar();
switch(c){
case 1:
        //密钥协商
        break;
case 2:
        //密钥校验
        break;
case 3:
        //密钥注销
        break;
case 4:
        //密钥查看
        break;

}
}
struct RequestMsg
{
    int cmdType; 	   //0-秘钥协商 1-秘钥校验 2-秘钥注销 3-秘钥查看
    char clientId[12]; //客户端ID, 是唯一的, 不同的客户端有不同的ID
    char authCode[65]; //消息验证码, 对r1进行验证
    char serverId[12]; //服务端ID
    char r1[64];       //客户端生成的随机字符串
};

秘钥协商流程:
1、对请求结构体RequestMsg进行赋值
    生成随机字符串r1,设置cmdType=0,clientID,serverID可以从配置文件或者环境变量
    中获得,最好写死,不然改代码需要重新编译和部署
    authCode对r1进行哈希运算hmac得到一个值;

2、对请求结构体进行报文编码操作,得到一个字符串
    char * outData;
    CodeFectory * factory=new RequestFactory(&msg);
    Codec *codec=factory->createCodec();
    codec->msgEncode(&outData);
3、链接密钥协商服务器
4、发送编码后的字符串给密钥协商服务器
5、等待接受服务端应答数据inData
6、解码服务端发来的应答数据到结构体RespondMsg
struct RespondMsg
{
    int rv; 		   //0-表示成功 -1-表示失败
    char clientId[12]; //客户端ID
    char serverId[12]; //服务端ID 
    char r2[64]; 	   //秘钥协商: 随机字符串, 秘钥查看: 秘钥  秘钥校验和注销:可不写 
    int seckeyid; 	   //秘钥ID :服务端生成的 
};
factory=new RespondFactory();
codec=factory->createCodec();
RespondMsg* pMsg=(RespondMsg*)codec->msgDecode(inData,len);
7、根据rv值判断密钥协商是否成功
8、客户端使用r1和服务端发来的r2进行哈希运算,得到一个新的哈希值seckey1,这个值就当作生成的秘钥。
9、将新的密钥信息写入共享内存
class NodeSHMInfo
{
public:
	int status;
	int seckeyID;
	char clientID[12];
	char serverID[12];
	char seckey[128];
};
10、断开与服务端的网络连接

使用hmac函数

HMAC_CTX *HMAC_CTX_new(void);
/*__owur*/ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
                            const EVP_MD *md, ENGINE *impl);
/*__owur*/ int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data,
                           size_t len);
/*__owur*/ int HMAC_Final(HMAC_CTX *ctx, unsigned char *md,
                          unsigned int *len);


unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
                    const unsigned char *d, size_t n, unsigned char *md,
                    unsigned int *md_len);

一个报错:

服务端和客户端生成密钥不一致

原因:服务端和客户端使用哈希函数时传参类型,必须一模一样,注意buf的长度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值