秘钥协商服务整体流程描述

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

1
2
3
4
5
struct Head
{
int total; //最多可以存放多少个
int useNum; //当前可用的个数
}

image-20220531073654443

1.秘钥协商的流程

  • 在秘钥协商客户端生成一随机字符串 - rand1
  • 客户端将rand1发送给秘钥协商服务器
  • 服务器接收客户端发送的rand1, 在服务器端生成一另外一个随机字符串rand2
  • 服务器将rand1和rand2进行混合运算生成一个新的字符串 - seckey1
    • 通过哈希函数
  • 服务器将生成的rand2发送给客户端
  • 客户端接收数据, 客户端有rand1和rand2
    • 通过哈希函数进行运算 - seckey2
  • 可以将seckey1和seckey2作为秘钥

2.秘钥校验

  • 当秘钥协商成功之后, 需要再次校验客户端和服务器生成的秘钥是否相同
    • 如何校验:
      • 将秘钥进行哈希运算, 比较散列值

3.秘钥注销

  • 不再继续使用的秘钥需要注销
    • 需要标记秘钥的状态:
      • bool status
        • status == 1: 可用
        • status == 0: 不可用

4.秘钥查看

  • 查看不是当前秘钥的信息
  • 查看的是历史秘钥
    • 根据网点查看
    • 根据日期查看

5.使用的数据结构

  • 秘钥协商客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 客户端给服务器发送数据的时候用到的数据结构
struct RequestMsg
{
//1 密钥协商 //2 密钥校验; // 3 密钥注销
int cmdType; // 报文类型
char clientId[12]; // 客户端编号
char authCode[65]; // 认证码 - openssl hmac
char serverId[12]; // 服务器端编号
char r1[64]; // 客户端随机数
};

- cmdType: 客户端请求的类型, 服务器根据这个变量做不同的处理
- clientId: 客户端的编号, 是唯一的
- serverId: 服务器的编号, 是唯一的
- authCode: 消息认证码, 判定消息是否被篡改过
- (原始数据 + 秘钥) * 哈希运算 = 散列值
- r1: 客户端生成的随机字符串, 生成秘钥其中的一部分原材料
  • 秘钥协商服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 服务器给客户端回复的时候用的到结构
struct RespondMsg
{
int rv; // 返回值
char clientId[12]; // 客户端编号
char serverId[12]; // 服务器编号
char r2[64]; // 服务器端随机数
int seckeyid; // 对称密钥编号 keysn
};

- rv: return value - > 服务器对客户端请求的处理结果
- 0: 正确
- -1: 错误
- clientId: 客户端的编号, 是唯一的
- serverId: 服务器的编号, 是唯一的
- r2: 服务器生成的随机字符串, 生成秘钥其中的一部分原材料
- seckeyid: 生成的新的秘钥之后, 需要编号, 该动作是有秘钥协商服务器完成的
  1. 写一个人机交互程序
1
2
3
4
5
6
7
8
9
10
11
12
13

printf("0-退出, 1-协商, 2-校验, 3-注销\n");
while(1)
{
// 键盘捕捉
cin >> sel;
switch(sel)
{
case 1:
// 秘钥协商
break;
}
}
  1. 用户输入1, 进入秘钥协商
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
创建一个 RequestMsg对象, 并初始化
将要发送的数据序列化 - 得到一个字符串
创建通信的套接字, 并且连接到秘钥协商服务器
发送序列化之后的字符串
阻塞等待接收服务器回发的数据 - > 字符串
服务器序列化之后得到的字符串
需要接接收的字符串解码, 数据还原得到RespondMsg对象
查看服务器处理结果 - > rv的值
// 服务器给客户端回复的时候用的到结构
struct RespondMsg
{
int rv; // 返回值
char clientId[12]; // 客户端编号
char serverId[12]; // 服务器编号
char r2[64]; // 服务器端随机数
int seckeyid; // 对称密钥编号 keysn
};
- rv: return value - > 服务器对客户端请求的处理结果
- 0: 正确
- -1: 错误
- clientId: 客户端的编号, 是唯一的
- serverId: 服务器的编号, 是唯一的
- r2: 服务器生成的随机字符串, 生成秘钥其中的一部分原材料
- seckeyid: 生成的新的秘钥之后, 需要编号, 该动作是有秘钥协商服务器完成的
失败 - > 直接退出, 通过用户
成功 -> 继续
通过服务器发送过来的r2和自己 的r1组合
进行哈希运算 -> 散列值 -> 秘钥
将生成的秘钥写入共享内存
class NodeSHMInfo {
public:
int status;
int seckeyID;
char clientID[12];
char serverID[12];
char seckey[128];
};

NodeSHMInfo 类型的变量可以从配置文件或者是环境变量中获取;