加密过程Step 1.1. 敏感信息的 Pack 操作,对齐字节并对数据进行初步保护因为 AES 算法是一种分组算法,而且每个分组必须是 32 位的整数倍,并且最小值为 128 位,我们需要对加密的数据进行 数据对齐,这里采用 16 字节即 128 位对齐。并且,为了保证数据的完整性,对数据加入头部和尾部,其中头部和尾部都有 标识符来表征数据的完整性。以上整个过程我们称之为 Pack 操作。 一旦该数据被意外截断,就可以通过头尾部检测到,无论发送方还是接收方都会丢弃此类数据,以保证系统安全。以下是 Pack 操作的具体步骤: 读取用户提供的需要加密的内容,对 password 的实际值 PASSWORD 进行 Pack 操作,使用到的数据结构参见 清单 3中的示例。数据在 Pack 操作后呈现的结构如 图 1所示: 清单 3. 头部结构的定义双击代码全选 1234567891011121314151617 struct DataHeader { #pragma pack(push, 1) // 使结构体 1 字节对齐 UINT32 canary1; // 标识,用于检测数据是否截断,设置值为 (0xDEADC0DE) UINT8 version; // 头部版本(以 0 开始) UINT8 reserved1; // 保留位 UINT16 offset; // 从开始到有效负载数据的偏移量(头部长度) UINT32 size; // 有效负载数据的长度 UINT16 reserved2; // 保留位 UINT8 reserved3; // 保留位 . UINT8 UIDsize; // UID 的长度 #pragma pack(pop) } header; // 备注 : 接下来的两个字段可以根据实际需要设置 // 文件的其余部分结构如下设置 // char[] UID; // UID 指每次会话的 SessionID(不含结尾的 NULL 符) // UINT8[] payload; // 需要传输的数据,即有效负载数据 // UINT32 canary2; // 标识,用于检测数据是否截断,设置值为 (0xDEADC0DE) 图 1. Pack 后的数据结构图为什么我们在敏感数据的头尾部加上标识 canary 呢? 这出自这样一个传说。大家知道 canary 是金丝雀的意思。古代挖煤的工人由于没有像现在 这么高级的瓦斯探测仪,所以往往不知道前方是不是危险区域,该不该进入。所以有一个工人想到了一个妙招,在挖煤的地点放一只金丝雀,如果 发现金丝雀站立不稳,就知道这里是危险区域,应马上离开。所以我们在数据的头尾部加上这样的标识,一旦数据发生异动,就可以及时丢弃异常数据, 报告错误。 对上述头部结构体的内容进行赋值之后,需要把特定内容转换为网络序以便网络传输, 如 清单 4所示: 清单 4. 设置头部结构的网络序双击代码全选 12345 // 从主机序转换为网络序,以便网络传输 . header.canary1 = htonl(header.canary1); header.offset = htons(header.offset); header.size = htonl(header.size); Canary2 = header.canary1;然后,对整个数据进行 16 字节的对齐操作,如 清单 5所示。 清单 5. 数据的 16 字节对齐双击代码全选 1234 UINT32 size = sizeof(header) + UID.size() + payload.size() + sizeof(header.canary1); if(size % 16) size += 16 - (size % 16); // 原数据需 copy 到上述 size 的结构中这样就会产生 0 到 15 个字节的空位,在图 1 中用 Padding dummy 表示。 Padding dummy 的长度在 0 到 15 个字节,其取决于 DataHeader, UID, Payload 和 Canary2 的长度和。 padding dummy 的值可以用空值填充。 (责任编辑:admin) |