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