Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include <fcntl.h>
12 : #include <unistd.h>
13 : #include <hccl/hccl_types.h>
14 : #include "hccl_nslb_md5.h"
15 :
16 : namespace hccl {
17 :
18 : // 初始化常量
19 : const unsigned char NSLBMD5::PADDING[64] = {
20 : 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22 : 0, 0, 0, 0, 0, 0, 0, 0, 0
23 : };
24 :
25 : const char NSLBMD5::HEX[16] = {
26 : '0', '1', '2', '3',
27 : '4', '5', '6', '7',
28 : '8', '9', 'a', 'b',
29 : 'c', 'd', 'e', 'f'
30 : };
31 :
32 : // F, G, H, I 是4个基本MD5函数
33 0 : inline uint32_t F(uint32_t x, uint32_t y, uint32_t z) {
34 0 : return (x & y) | (~x & z);
35 : }
36 :
37 0 : inline uint32_t G(uint32_t x, uint32_t y, uint32_t z) {
38 0 : return (x & z) | (y & ~z);
39 : }
40 :
41 0 : inline uint32_t H(uint32_t x, uint32_t y, uint32_t z) {
42 0 : return x ^ y ^ z;
43 : }
44 :
45 0 : inline uint32_t I(uint32_t x, uint32_t y, uint32_t z) {
46 0 : return y ^ (x | ~z);
47 : }
48 :
49 : // 左循环移位操作
50 0 : inline uint32_t ROTATE_LEFT(uint32_t x, int n) {
51 0 : return (x << n) | (x >> (NSLB_MD5_RESERVE - n));
52 : }
53 :
54 : // FF, GG, HH, II 是四轮变换中的基本操作
55 0 : inline void FF(uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
56 0 : a += F(b, c, d) + x + ac;
57 0 : a = ROTATE_LEFT(a, s);
58 0 : a += b;
59 0 : }
60 :
61 0 : inline void GG(uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
62 0 : a += G(b, c, d) + x + ac;
63 0 : a = ROTATE_LEFT(a, s);
64 0 : a += b;
65 0 : }
66 :
67 0 : inline void HH(uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
68 0 : a += H(b, c, d) + x + ac;
69 0 : a = ROTATE_LEFT(a, s);
70 0 : a += b;
71 0 : }
72 :
73 0 : inline void II(uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
74 0 : a += I(b, c, d) + x + ac;
75 0 : a = ROTATE_LEFT(a, s);
76 0 : a += b;
77 0 : }
78 :
79 0 : void NSLBMD5::init() {
80 0 : finalized = false;
81 :
82 : // 初始化状态为标准值
83 0 : count[0] = count[1] = 0;
84 : // 初始化MD5缓冲区
85 0 : state[0] = 0x67452301;
86 0 : state[NSLB_MD5_STATE1] = 0xEFCDAB89;
87 0 : state[NSLB_MD5_STATE2] = 0x98BADCFE;
88 0 : state[NSLB_MD5_STATE3] = 0x10325476;
89 0 : }
90 :
91 0 : NSLBMD5::NSLBMD5() {
92 0 : init();
93 0 : }
94 :
95 0 : NSLBMD5::NSLBMD5(const std::string& text) {
96 0 : init();
97 0 : update(text.c_str(), text.length());
98 0 : finalize();
99 0 : }
100 :
101 : // 解码字节数组为32位整数数组 - 改进实现,避免使用强制类型转换
102 0 : void NSLBMD5::decode(uint32_t output[], const uint8_t input[], size_t len) {
103 : // 使用std::memcpy安全地复制内存,避免强制类型转换
104 0 : size_t num_ints = len / NSLB_MD5_4;
105 0 : for (size_t i = 0; i < num_ints; ++i) {
106 0 : (void)memcpy_s(&output[i], sizeof(uint32_t), &input[i * NSLB_MD5_4], sizeof(uint32_t));
107 : }
108 0 : }
109 :
110 :
111 : // 编码32位整数数组为字节数组
112 0 : void NSLBMD5::encode(unsigned char output[], const uint32_t input[], size_t len) {
113 0 : for (size_t i = 0, j = 0; j < len; i++, j += NSLB_MD5_4) {
114 0 : output[j] = input[i] & 0xff;
115 0 : output[j + NSLB_MD5_STATE1] = (input[i] >> NSLB_MD5_8) & 0xff;
116 0 : output[j + NSLB_MD5_STATE2] = (input[i] >> NSLB_MD5_16) & 0xff;
117 0 : output[j + NSLB_MD5_STATE3] = (input[i] >> NSLB_MD5_24) & 0xff;
118 : }
119 0 : }
120 :
121 : /**
122 : * 背景:标准的MD5算法,主要功能是64字节处理
123 : * 参考文献:RFC 1321: The MD5 Message-Digest Algorithm
124 : * 作者:Ron Rivest
125 : * 发布日期:1992年4月
126 : */
127 0 : void NSLBMD5::update(const unsigned char input[], size_t length) {
128 : // 计算还需要填充多少字节才能达到64字节的倍数
129 0 : unsigned int index = count[0] / NSLB_MD5ENCODE_COUNT % NSLB_MD5_TOTAL;
130 :
131 : // 更新消息长度
132 0 : if ((count[0] += (length << NSLB_MD5_COUNTLEN3)) < (length << NSLB_MD5_COUNTLEN3)) {
133 0 : count[1]++;
134 : }
135 0 : count[1] += (length >> NSLB_MD5_COUNTLEN29);
136 :
137 : // 计算需要处理多少个完整的64字节块
138 0 : unsigned int firstpart = NSLB_MD5_TOTAL - index;
139 : unsigned int i;
140 :
141 : // 处理消息的第一部分(如果有)
142 0 : if (length >= firstpart) {
143 0 : (void)memcpy_s(&buffer[index], firstpart, input, firstpart);
144 0 : transform(buffer);
145 :
146 : // 处理剩余的64字节块
147 0 : for (i = firstpart; i + (NSLB_MD5_TOTAL - 1) < length; i += NSLB_MD5_TOTAL)
148 0 : transform(&input[i]);
149 :
150 0 : index = 0;
151 : } else {
152 0 : i = 0;
153 : }
154 :
155 : // 存储剩余的字节
156 0 : (void)memcpy_s(&buffer[index], length - i, &input[i], length - i);
157 0 : }
158 :
159 0 : void NSLBMD5::update(const char input[], size_t length) {
160 : // 转换为uint8_t指针,使用标准C++转换
161 0 : update(reinterpret_cast<const uint8_t*>(input), length);
162 0 : }
163 :
164 : /**
165 : * 背景:标准的MD5算法,主要功能是MD5算法的核心变换函数,处理一个64字节的块
166 : * 参考文献:RFC 1321: The MD5 Message-Digest Algorithm
167 : * 作者:Ron Rivest
168 : * 发布日期:1992年4月
169 : */
170 0 : void NSLBMD5::transform(const unsigned char block[64]) {
171 0 : uint32_t a = state[0], b = state[NSLB_MD5_STATE1], c = state[NSLB_MD5_STATE2], d = state[NSLB_MD5_STATE3], x[NSLB_MD5_16];
172 :
173 0 : decode(x, block, NSLB_MD5_TOTAL);
174 :
175 : // 第一轮
176 0 : FF(a, b, c, d, x[ 0], NSLB_MD5_7, 0xd76aa478);
177 0 : FF(d, a, b, c, x[NSLB_MD5_HASH1], NSLB_MD5_12, 0xe8c7b756);
178 0 : FF(c, d, a, b, x[NSLB_MD5_HASH2], NSLB_MD5_17, 0x242070db);
179 0 : FF(b, c, d, a, x[NSLB_MD5_HASH3], NSLB_MD5_22, 0xc1bdceee);
180 0 : FF(a, b, c, d, x[NSLB_MD5_HASH4], NSLB_MD5_7, 0xf57c0faf);
181 0 : FF(d, a, b, c, x[NSLB_MD5_HASH5], NSLB_MD5_12, 0x4787c62a);
182 0 : FF(c, d, a, b, x[NSLB_MD5_HASH6], NSLB_MD5_17, 0xa8304613);
183 0 : FF(b, c, d, a, x[NSLB_MD5_HASH7], NSLB_MD5_22, 0xfd469501);
184 0 : FF(a, b, c, d, x[NSLB_MD5_HASH8], NSLB_MD5_7, 0x698098d8);
185 0 : FF(d, a, b, c, x[NSLB_MD5_HASH9], NSLB_MD5_12, 0x8b44f7af);
186 0 : FF(c, d, a, b, x[NSLB_MD5_HASH10], NSLB_MD5_17, 0xffff5bb1);
187 0 : FF(b, c, d, a, x[NSLB_MD5_HASH11], NSLB_MD5_22, 0x895cd7be);
188 0 : FF(a, b, c, d, x[NSLB_MD5_HASH12], NSLB_MD5_7, 0x6b901122);
189 0 : FF(d, a, b, c, x[NSLB_MD5_HASH13], NSLB_MD5_12, 0xfd987193);
190 0 : FF(c, d, a, b, x[NSLB_MD5_HASH14], NSLB_MD5_17, 0xa679438e);
191 0 : FF(b, c, d, a, x[NSLB_MD5_HASH15], NSLB_MD5_22, 0x49b40821);
192 :
193 : // 第二轮
194 0 : GG(a, b, c, d, x[NSLB_MD5_HASH1], NSLB_MD5_5, 0xf61e2562);
195 0 : GG(d, a, b, c, x[NSLB_MD5_HASH6], NSLB_MD5_9, 0xc040b340);
196 0 : GG(c, d, a, b, x[NSLB_MD5_HASH11], NSLB_MD5_14, 0x265e5a51);
197 0 : GG(b, c, d, a, x[ 0], NSLB_MD5_20, 0xe9b6c7aa);
198 0 : GG(a, b, c, d, x[NSLB_MD5_HASH5], NSLB_MD5_5, 0xd62f105d);
199 0 : GG(d, a, b, c, x[NSLB_MD5_HASH10], NSLB_MD5_9, 0x02441453);
200 0 : GG(c, d, a, b, x[NSLB_MD5_HASH15], NSLB_MD5_14, 0xd8a1e681);
201 0 : GG(b, c, d, a, x[NSLB_MD5_HASH4], NSLB_MD5_20, 0xe7d3fbc8);
202 0 : GG(a, b, c, d, x[NSLB_MD5_HASH9], NSLB_MD5_5, 0x21e1cde6);
203 0 : GG(d, a, b, c, x[NSLB_MD5_HASH14], NSLB_MD5_9, 0xc33707d6);
204 0 : GG(c, d, a, b, x[NSLB_MD5_HASH3], NSLB_MD5_14, 0xf4d50d87);
205 0 : GG(b, c, d, a, x[NSLB_MD5_HASH8], NSLB_MD5_20, 0x455a14ed);
206 0 : GG(a, b, c, d, x[NSLB_MD5_HASH13], NSLB_MD5_5, 0xa9e3e905);
207 0 : GG(d, a, b, c, x[NSLB_MD5_HASH2], NSLB_MD5_9, 0xfcefa3f8);
208 0 : GG(c, d, a, b, x[NSLB_MD5_HASH7], NSLB_MD5_14, 0x676f02d9);
209 0 : GG(b, c, d, a, x[NSLB_MD5_HASH12], NSLB_MD5_20, 0x8d2a4c8a);
210 :
211 : // 第三轮
212 0 : HH(a, b, c, d, x[NSLB_MD5_HASH5], NSLB_MD5_4, 0xfffa3942);
213 0 : HH(d, a, b, c, x[NSLB_MD5_HASH8], NSLB_MD5_11, 0x8771f681);
214 0 : HH(c, d, a, b, x[NSLB_MD5_HASH11], NSLB_MD5_16, 0x6d9d6122);
215 0 : HH(b, c, d, a, x[NSLB_MD5_HASH14], NSLB_MD5_23, 0xfde5380c);
216 0 : HH(a, b, c, d, x[NSLB_MD5_HASH1], NSLB_MD5_4, 0xa4beea44);
217 0 : HH(d, a, b, c, x[NSLB_MD5_HASH4], NSLB_MD5_11, 0x4bdecfa9);
218 0 : HH(c, d, a, b, x[NSLB_MD5_HASH7], NSLB_MD5_16, 0xf6bb4b60);
219 0 : HH(b, c, d, a, x[NSLB_MD5_HASH10], NSLB_MD5_23, 0xbebfbc70);
220 0 : HH(a, b, c, d, x[NSLB_MD5_HASH13], NSLB_MD5_4, 0x289b7ec6);
221 0 : HH(d, a, b, c, x[ 0], NSLB_MD5_11, 0xeaa127fa);
222 0 : HH(c, d, a, b, x[NSLB_MD5_HASH3], NSLB_MD5_16, 0xd4ef3085);
223 0 : HH(b, c, d, a, x[NSLB_MD5_HASH6], NSLB_MD5_23, 0x04881d05);
224 0 : HH(a, b, c, d, x[NSLB_MD5_HASH9], NSLB_MD5_4, 0xd9d4d039);
225 0 : HH(d, a, b, c, x[NSLB_MD5_HASH12], NSLB_MD5_11, 0xe6db99e5);
226 0 : HH(c, d, a, b, x[NSLB_MD5_HASH15], NSLB_MD5_16, 0x1fa27cf8);
227 0 : HH(b, c, d, a, x[NSLB_MD5_HASH2], NSLB_MD5_23, 0xc4ac5665);
228 :
229 : // 第四轮
230 0 : II(a, b, c, d, x[ 0], NSLB_MD5_6, 0xf4292244);
231 0 : II(d, a, b, c, x[NSLB_MD5_HASH7], NSLB_MD5_10, 0x432aff97);
232 0 : II(c, d, a, b, x[NSLB_MD5_HASH14], NSLB_MD5_15, 0xab9423a7);
233 0 : II(b, c, d, a, x[NSLB_MD5_HASH5], NSLB_MD5_21, 0xfc93a039);
234 0 : II(a, b, c, d, x[NSLB_MD5_HASH12], NSLB_MD5_6, 0x655b59c3);
235 0 : II(d, a, b, c, x[NSLB_MD5_HASH3], NSLB_MD5_10, 0x8f0ccc92);
236 0 : II(c, d, a, b, x[NSLB_MD5_HASH10], NSLB_MD5_15, 0xffeff47d);
237 0 : II(b, c, d, a, x[NSLB_MD5_HASH1], NSLB_MD5_21, 0x85845dd1);
238 0 : II(a, b, c, d, x[NSLB_MD5_HASH8], NSLB_MD5_6, 0x6fa87e4f);
239 0 : II(d, a, b, c, x[NSLB_MD5_HASH15], NSLB_MD5_10, 0xfe2ce6e0);
240 0 : II(c, d, a, b, x[NSLB_MD5_HASH6], NSLB_MD5_15, 0xa3014314);
241 0 : II(b, c, d, a, x[NSLB_MD5_HASH13], NSLB_MD5_21, 0x4e0811a1);
242 0 : II(a, b, c, d, x[NSLB_MD5_HASH4], NSLB_MD5_6, 0xf7537e82);
243 0 : II(d, a, b, c, x[NSLB_MD5_HASH11], NSLB_MD5_10, 0xbd3af235);
244 0 : II(c, d, a, b, x[NSLB_MD5_HASH2], NSLB_MD5_15, 0x2ad7d2bb);
245 0 : II(b, c, d, a, x[NSLB_MD5_HASH9], NSLB_MD5_21, 0xeb86d391);
246 :
247 : // 将变换结果添加到当前状态
248 0 : state[0] += a;
249 0 : state[NSLB_MD5_STATE1] += b;
250 0 : state[NSLB_MD5_STATE2] += c;
251 0 : state[NSLB_MD5_STATE3] += d;
252 :
253 : // 清除缓冲区
254 0 : (void)memset_s(x, sizeof(x), 0, sizeof(x));
255 0 : }
256 :
257 : // 完成MD5计算
258 0 : NSLBMD5& NSLBMD5::finalize() {
259 : static unsigned char bits[8];
260 : unsigned int index, padLen;
261 :
262 : // 存储消息长度
263 0 : encode(bits, count, NSLB_MD5ENCODE_COUNT);
264 :
265 : // 填充消息使其长度为56字节的倍数
266 0 : index = count[0] / NSLB_MD5ENCODE_COUNT % NSLB_MD5_TOTAL;
267 0 : padLen = (index < NSLB_MD5_56) ? (NSLB_MD5_56 - index) : (NSLB_MD5_120 - index);
268 0 : update(PADDING, padLen);
269 :
270 : // 附加长度
271 0 : update(bits, NSLB_MD5ENCODE_COUNT);
272 :
273 : // 存储状态到digest
274 0 : encode(digest, state, NSLB_MD5_DIGEST);
275 :
276 : // 清除敏感信息
277 0 : (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
278 0 : (void)memset_s(count, sizeof(count), 0, sizeof(count));
279 :
280 0 : finalized = true;
281 0 : return *this;
282 : }
283 :
284 : // 转换为十六进制字符串
285 0 : std::string NSLBMD5::hexdigest() const {
286 0 : if (!finalized)
287 0 : return "";
288 0 : std::string result;
289 0 : result.reserve(NSLB_MD5_RESERVE);
290 :
291 0 : for (unsigned int i = 0; i < NSLB_MD5_DIGEST; i++) {
292 : // 手动转换为十六进制字符
293 0 : uint8_t byte = digest[i];
294 0 : result.push_back(HEX[(byte >> NSLB_MD5_STATE4) & 0xF]);
295 0 : result.push_back(HEX[byte & 0xF]);
296 : }
297 :
298 0 : return result;
299 0 : }
300 :
301 0 : std::ostream& operator<<(std::ostream& out, NSLBMD5 md5) {
302 0 : return out << md5.hexdigest();
303 : }
304 :
305 0 : std::string nslb_md5(const std::string str) {
306 0 : NSLBMD5 md5 = NSLBMD5(str);
307 0 : return md5.hexdigest();
308 : }
309 :
310 : // 计算NslbDpRankInfo结构体向量的MD5
311 0 : void NSLBMD5::calculateRankInfoMd5(const std::vector<NslbDpRankInfo>& rankInfo, uint8_t commMd5Sum[16]) {
312 0 : NSLBMD5 md5;
313 :
314 : // 遍历向量中的每个结构体元素
315 0 : for (const auto& info : rankInfo) {
316 : // 将结构体转换为字节数组并更新MD5
317 0 : md5.update(reinterpret_cast<const unsigned char*>(&info), sizeof(NslbDpRankInfo));
318 : }
319 :
320 : // 完成MD5计算
321 0 : md5.finalize();
322 :
323 : // 将结果复制到输出数组
324 0 : (void)memcpy_s(commMd5Sum, NSLB_MD5_DIGEST, md5.digest, NSLB_MD5_DIGEST);
325 0 : }
326 :
327 : // 新增:计算TableFourRankInfo结构体向量的MD5
328 0 : void NSLBMD5::calculateTableFourRankInfoMd5(const std::vector<TableFourRankInfo>& rankInfo, uint8_t commMd5Sum[16]) {
329 0 : NSLBMD5 md5;
330 :
331 : // 遍历向量中的每个结构体元素
332 0 : for (const auto& info : rankInfo) {
333 : // 将结构体转换为字节数组并更新MD5
334 0 : md5.update(reinterpret_cast<const uint8_t*>(&info), sizeof(TableFourRankInfo));
335 : }
336 :
337 : // 完成MD5计算
338 0 : md5.finalize();
339 : // 将结果复制到输出数组
340 0 : (void)memcpy_s(commMd5Sum, NSLB_MD5_DIGEST, md5.digest, NSLB_MD5_DIGEST);
341 0 : }
342 :
343 : // 将MD5值转换为字符串
344 0 : std::string NSLBMD5::md5ToString(const uint8_t md5[16]) {
345 0 : std::string result;
346 0 : result.reserve(NSLB_MD5_RESERVE);
347 :
348 0 : for (unsigned int i = 0; i < NSLB_MD5_DIGEST; i++) {
349 : // 手动转换为十六进制字符
350 0 : uint8_t byte = md5[i];
351 0 : result.push_back(HEX[(byte >> NSLB_MD5_STATE1) & 0xF]);
352 0 : result.push_back(HEX[byte & 0xF]);
353 : }
354 :
355 0 : return result;
356 0 : }
357 :
358 : }
|