阿里云的物联网平台设备端使用mqtt时必须要使用阿里云加密算法通过设备三元组算出来的username、password、clientId才可以连接成功
使用mqtt.fx、mqttBox等客户端软件时必须要根据设备三元组计算出正确的登录信息,最近在使用qt,所以使用qt写了这么一个小工具
做出来的基本效果为:
在下面输入阿里云物联网平台设备的三元组信息,即可生成对应得mqtt用户名密码和ID信息。
使用的阿里云加密算法代码为:
1 #include"hmac.h" 2 #include <stdio.h> 3 #include <stdint.h> 4 #include <string.h> 5 #define PRODUCTKEY_MAXLEN (20) 6 #define DEVICENAME_MAXLEN (32) 7 #define DEVICESECRET_MAXLEN (64) 8 9 #define SIGN_SOURCE_MAXLEN (200) 10 #define CLIENTID_MAXLEN (150) 11 #define USERNAME_MAXLEN (64) 12 #define PASSWORD_MAXLEN (65) 13 14 /****************************** 15 * hmac-sha256 implement below 16 ******************************/ 17 #define SHA256_KEY_IOPAD_SIZE (64) 18 #define SHA256_DIGEST_SIZE (32) 19 20 static void utils_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32]); 21 22 static const uint32_t K[] = { 23 0x428A2F98, 24 0x71374491, 25 0xB5C0FBCF, 26 0xE9B5DBA5, 27 0x3956C25B, 28 0x59F111F1, 29 0x923F82A4, 30 0xAB1C5ED5, 31 0xD807AA98, 32 0x12835B01, 33 0x243185BE, 34 0x550C7DC3, 35 0x72BE5D74, 36 0x80DEB1FE, 37 0x9BDC06A7, 38 0xC19BF174, 39 0xE49B69C1, 40 0xEFBE4786, 41 0x0FC19DC6, 42 0x240CA1CC, 43 0x2DE92C6F, 44 0x4A7484AA, 45 0x5CB0A9DC, 46 0x76F988DA, 47 0x983E5152, 48 0xA831C66D, 49 0xB00327C8, 50 0xBF597FC7, 51 0xC6E00BF3, 52 0xD5A79147, 53 0x06CA6351, 54 0x14292967, 55 0x27B70A85, 56 0x2E1B2138, 57 0x4D2C6DFC, 58 0x53380D13, 59 0x650A7354, 60 0x766A0ABB, 61 0x81C2C92E, 62 0x92722C85, 63 0xA2BFE8A1, 64 0xA81A664B, 65 0xC24B8B70, 66 0xC76C51A3, 67 0xD192E819, 68 0xD6990624, 69 0xF40E3585, 70 0x106AA070, 71 0x19A4C116, 72 0x1E376C08, 73 0x2748774C, 74 0x34B0BCB5, 75 0x391C0CB3, 76 0x4ED8AA4A, 77 0x5B9CCA4F, 78 0x682E6FF3, 79 0x748F82EE, 80 0x78A5636F, 81 0x84C87814, 82 0x8CC70208, 83 0x90BEFFFA, 84 0xA4506CEB, 85 0xBEF9A3F7, 86 0xC67178F2, 87 }; 88 89 #define SHR(x, n) ((x & 0xFFFFFFFF) >> n) 90 #define ROTR(x, n) (SHR(x, n) | (x << (32 - n))) 91 92 #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) 93 #define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) 94 95 #define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) 96 #define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) 97 98 #define F0(x, y, z) ((x & y) | (z & (x | y))) 99 #define F1(x, y, z) (z ^ (x & (y ^ z))) 100 101 #define R(t) 102 ( 103 W[t] = S1(W[t - 2]) + W[t - 7] + 104 S0(W[t - 15]) + W[t - 16]) 105 106 #define P(a, b, c, d, e, f, g, h, x, K) 107 { 108 temp1 = h + S3(e) + F1(e, f, g) + K + x; 109 temp2 = S2(a) + F0(a, b, c); 110 d += temp1; 111 h = temp1 + temp2; 112 } 113 /** 114 * rief SHA-256 context structure 115 */ 116 typedef struct 117 { 118 uint32_t total[2]; /*!< number of bytes processed */ 119 uint32_t state[8]; /*!< intermediate digest state */ 120 unsigned char buffer[64]; /*!< data block being processed */ 121 int is224; /*!< 0 => SHA-256, else SHA-224 */ 122 } iot_sha256_context; 123 124 #ifndef PUT_UINT32_BE 125 #define PUT_UINT32_BE(n, b, i) 126 do 127 { 128 (b)[(i)] = (unsigned char)((n) >> 24); 129 (b)[(i) + 1] = (unsigned char)((n) >> 16); 130 (b)[(i) + 2] = (unsigned char)((n) >> 8); 131 (b)[(i) + 3] = (unsigned char)((n)); 132 } while (0) 133 #endif 134 135 /* 136 * 32-bit integer manipulation macros (big endian) 137 */ 138 #ifndef GET_UINT32_BE 139 #define GET_UINT32_BE(n, b, i) 140 do 141 { 142 (n) = ((uint32_t)(b)[(i)] << 24) | ((uint32_t)(b)[(i) + 1] << 16) | ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); 143 } while (0) 144 #endif 145 static const unsigned char sha256_padding[64] = { 146 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 150 151 void utils_sha256_process(iot_sha256_context *ctx, const unsigned char data[64]) 152 { 153 uint32_t temp1, temp2, W[64]; 154 uint32_t A[8]; 155 unsigned int i; 156 157 for (i = 0; i < 8; i++) 158 { 159 A[i] = ctx->state[i]; 160 } 161 162 for (i = 0; i < 64; i++) 163 { 164 if (i < 16) 165 { 166 GET_UINT32_BE(W[i], data, 4 * i); 167 } 168 else 169 { 170 R(i); 171 } 172 173 P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i]); 174 175 temp1 = A[7]; 176 A[7] = A[6]; 177 A[6] = A[5]; 178 A[5] = A[4]; 179 A[4] = A[3]; 180 A[3] = A[2]; 181 A[2] = A[1]; 182 A[1] = A[0]; 183 A[0] = temp1; 184 } 185 186 for (i = 0; i < 8; i++) 187 { 188 ctx->state[i] += A[i]; 189 } 190 } 191 void utils_sha256_init(iot_sha256_context *ctx) 192 { 193 memset(ctx, 0, sizeof(iot_sha256_context)); 194 } 195 196 void utils_sha256_starts(iot_sha256_context *ctx) 197 { 198 int is224 = 0; 199 ctx->total[0] = 0; 200 ctx->total[1] = 0; 201 202 if (is224 == 0) 203 { 204 /* SHA-256 */ 205 ctx->state[0] = 0x6A09E667; 206 ctx->state[1] = 0xBB67AE85; 207 ctx->state[2] = 0x3C6EF372; 208 ctx->state[3] = 0xA54FF53A; 209 ctx->state[4] = 0x510E527F; 210 ctx->state[5] = 0x9B05688C; 211 ctx->state[6] = 0x1F83D9AB; 212 ctx->state[7] = 0x5BE0CD19; 213 } 214 215 ctx->is224 = is224; 216 } 217 void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, uint32_t ilen) 218 { 219 size_t fill; 220 uint32_t left; 221 222 if (ilen == 0) 223 { 224 return; 225 } 226 227 left = ctx->total[0] & 0x3F; 228 fill = 64 - left; 229 230 ctx->total[0] += (uint32_t)ilen; 231 ctx->total[0] &= 0xFFFFFFFF; 232 233 if (ctx->total[0] < (uint32_t)ilen) 234 { 235 ctx->total[1]++; 236 } 237 238 if (left && ilen >= fill) 239 { 240 memcpy((void *)(ctx->buffer + left), input, fill); 241 utils_sha256_process(ctx, ctx->buffer); 242 input += fill; 243 ilen -= fill; 244 left = 0; 245 } 246 247 while (ilen >= 64) 248 { 249 utils_sha256_process(ctx, input); 250 input += 64; 251 ilen -= 64; 252 } 253 254 if (ilen > 0) 255 { 256 memcpy((void *)(ctx->buffer + left), input, ilen); 257 } 258 } 259 260 void utils_sha256_finish(iot_sha256_context *ctx, uint8_t output[32]) 261 { 262 uint32_t last, padn; 263 uint32_t high, low; 264 unsigned char msglen[8]; 265 266 high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); 267 low = (ctx->total[0] << 3); 268 269 PUT_UINT32_BE(high, msglen, 0); 270 PUT_UINT32_BE(low, msglen, 4); 271 272 last = ctx->total[0] & 0x3F; 273 padn = (last < 56) ? (56 - last) : (120 - last); 274 275 utils_sha256_update(ctx, sha256_padding, padn); 276 utils_sha256_update(ctx, msglen, 8); 277 278 PUT_UINT32_BE(ctx->state[0], output, 0); 279 PUT_UINT32_BE(ctx->state[1], output, 4); 280 PUT_UINT32_BE(ctx->state[2], output, 8); 281 PUT_UINT32_BE(ctx->state[3], output, 12); 282 PUT_UINT32_BE(ctx->state[4], output, 16); 283 PUT_UINT32_BE(ctx->state[5], output, 20); 284 PUT_UINT32_BE(ctx->state[6], output, 24); 285 286 if (ctx->is224 == 0) 287 { 288 PUT_UINT32_BE(ctx->state[7], output, 28); 289 } 290 } 291 292 static void _hex2str(uint8_t *input, uint16_t input_len, char *output) 293 { 294 char *zEncode = "0123456789ABCDEF"; 295 int i = 0, j = 0; 296 297 for (i = 0; i < input_len; i++) 298 { 299 output[j++] = zEncode[(input[i] >> 4) & 0xf]; 300 output[j++] = zEncode[(input[i]) & 0xf]; 301 } 302 } 303 304 static void utils_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32]) 305 { 306 iot_sha256_context context; 307 uint8_t k_ipad[SHA256_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ 308 uint8_t k_opad[SHA256_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ 309 int32_t i; 310 311 if ((NULL == msg) || (NULL == key) || (NULL == output)) 312 { 313 return; 314 } 315 316 if (key_len > SHA256_KEY_IOPAD_SIZE) 317 { 318 return; 319 } 320 321 /* start out by storing key in pads */ 322 memset(k_ipad, 0, sizeof(k_ipad)); 323 memset(k_opad, 0, sizeof(k_opad)); 324 memcpy(k_ipad, key, key_len); 325 memcpy(k_opad, key, key_len); 326 327 /* XOR key with ipad and opad values */ 328 for (i = 0; i < SHA256_KEY_IOPAD_SIZE; i++) 329 { 330 k_ipad[i] ^= 0x36; 331 k_opad[i] ^= 0x5c; 332 } 333 334 /* perform inner SHA */ 335 utils_sha256_init(&context); /* init context for 1st pass */ 336 utils_sha256_starts(&context); /* setup context for 1st pass */ 337 utils_sha256_update(&context, k_ipad, SHA256_KEY_IOPAD_SIZE); /* start with inner pad */ 338 utils_sha256_update(&context, msg, msg_len); /* then text of datagram */ 339 utils_sha256_finish(&context, output); /* finish up 1st pass */ 340 341 /* perform outer SHA */ 342 utils_sha256_init(&context); /* init context for 2nd pass */ 343 utils_sha256_starts(&context); /* setup context for 2nd pass */ 344 utils_sha256_update(&context, k_opad, SHA256_KEY_IOPAD_SIZE); /* start with outer pad */ 345 utils_sha256_update(&context, output, SHA256_DIGEST_SIZE); /* then results of 1st hash */ 346 utils_sha256_finish(&context, output); /* finish up 2nd pass */ 347 } 348 349 #define TIMESTAMP_VALUE "2524608000000" 350 #define MQTT_CLINETID_KV "|timestamp=2524608000000,_v=paho-c-1.0.0,securemode=3,signmethod=hmacsha256,lan=C|" 351 352 int aiotMqttSign(const char *productKey, const char *deviceName, const char *deviceSecret, 353 char clientId[150], char username[64], char password[65]) 354 { 355 char deviceId[PRODUCTKEY_MAXLEN + DEVICENAME_MAXLEN + 2] = {0}; 356 char macSrc[SIGN_SOURCE_MAXLEN] = {0}; 357 uint8_t macRes[32] = {0}; 358 int res; 359 360 /* check parameters */ 361 if (productKey == NULL || deviceName == NULL || deviceSecret == NULL || 362 clientId == NULL || username == NULL || password == NULL) 363 { 364 return -1; 365 } 366 if ((strlen(productKey) > PRODUCTKEY_MAXLEN) || (strlen(deviceName) > DEVICENAME_MAXLEN) || 367 (strlen(deviceSecret) > DEVICESECRET_MAXLEN)) 368 { 369 return -1; 370 } 371 372 /* setup deviceId */ 373 memcpy(deviceId, deviceName, strlen(deviceName)); 374 memcpy(deviceId + strlen(deviceId), "&", strlen("&")); 375 memcpy(deviceId + strlen(deviceId), productKey, strlen(productKey)); 376 377 /* setup clientid */ 378 memcpy(clientId, deviceId, strlen(deviceId)); 379 memcpy(clientId + strlen(deviceId), MQTT_CLINETID_KV, strlen(MQTT_CLINETID_KV)); 380 memset(clientId + strlen(deviceId) + strlen(MQTT_CLINETID_KV), 0, 1); 381 382 /* setup username */ 383 memcpy(username, deviceId, strlen(deviceId)); 384 memset(username + strlen(deviceId), 0, 1); 385 386 /* setup password */ 387 memcpy(macSrc, "clientId", strlen("clientId")); 388 memcpy(macSrc + strlen(macSrc), deviceId, strlen(deviceId)); 389 memcpy(macSrc + strlen(macSrc), "deviceName", strlen("deviceName")); 390 memcpy(macSrc + strlen(macSrc), deviceName, strlen(deviceName)); 391 memcpy(macSrc + strlen(macSrc), "productKey", strlen("productKey")); 392 memcpy(macSrc + strlen(macSrc), productKey, strlen(productKey)); 393 memcpy(macSrc + strlen(macSrc), "timestamp", strlen("timestamp")); 394 memcpy(macSrc + strlen(macSrc), TIMESTAMP_VALUE, strlen(TIMESTAMP_VALUE)); 395 396 utils_hmac_sha256((uint8_t *)macSrc, strlen(macSrc), (uint8_t *)deviceSecret, 397 strlen(deviceSecret), macRes); 398 memset(password, 0, PASSWORD_MAXLEN); 399 printf("password: %s ", password); 400 _hex2str(macRes, sizeof(macRes), password); 401 return 0; 402 }
qt窗口使用的是qwidget,继承的子类名称为myWidget,myWidget.cpp
代码为:
#include "mywidget.h" #include <QFont> #include "hmac.h" #include "stdio.h" #include "string.h" myWidget::myWidget(QWidget *parent) : QWidget(parent) { this->resize(1000,500); setWindowTitle("阿里登录信息计算器"); QFont font; font.setPointSize(10); setFont(font); m_but=new QPushButton("计算",this); label_pwd=new QLabel("password",this); label_pwd->move(0,0); label_pwd->resize(1000,30); label_pwd->setStyleSheet("background-color:red"); m_pwd=new QLineEdit(this); m_pwd->move(0,30); m_pwd->resize(1000,30); //m_pwd->setText("password"); label_id=new QLabel("clientId",this); label_id->move(0,60); label_id->resize(1000,30); label_id->setStyleSheet("background-color:yellow"); m_id=new QLineEdit(this); m_id->move(0,90); m_id->resize(1000,30); // m_id->setText("clientId"); label_user=new QLabel("username",this); label_user->move(0,120); label_user->resize(1000,30); label_user->setStyleSheet("background-color:red"); m_name=new QLineEdit(this); m_name->move(0,150); m_name->resize(1000,30); //m_name->setText("username"); QFont font1("Microsoft",10,75); label_tip=new QLabel("请输入以下参数:",this); label_tip->setFont(font1); label_tip->move(0,200); label_tip->resize(1000,30); //label_tip->setStyleSheet("background-color:yellow"); label_key=new QLabel("productkey",this); label_key->move(0,230); label_key->resize(1000,30); label_key->setStyleSheet("background-color:red"); m_prd_key=new QLineEdit("a1Fk4iW6xld",this); m_prd_key->move(0,260); m_prd_key->resize(1000,30); label_srt=new QLabel("deviceserect",this); label_srt->move(0,290); label_srt->resize(1000,30); label_srt->setStyleSheet("background-color:yellow"); m_dev_srt=new QLineEdit("SbsnTLdS1GKGEsHUDIA9V1AJJ1FvV1dp",this); m_dev_srt->move(0,320); m_dev_srt->resize(1000,30); label_name=new QLabel("devicename",this); label_name->move(0,350); label_name->resize(1000,30); label_name->setStyleSheet("background-color:red"); m_dev_name=new QLineEdit("powermac",this); m_dev_name->move(0,380); m_dev_name->resize(1000,30); m_but->move(0,410); m_but->resize(150,50); m_brower=new QMessageBox(this); m_layout=new QHBoxLayout(this); connect(m_but,SIGNAL(clicked()),this,SLOT(calpwd())); } myWidget::~myWidget() { } void myWidget::calpwd(void){ char clientId[150] = {0}; char username[65] = {0}; char password[65] = {0}; QByteArray prd_key; prd_key.append(this->m_prd_key->text()); QByteArray dev_name; dev_name.append(this->m_dev_name->text()); QByteArray dev_srt; dev_srt.append(this->m_dev_srt->text()); aiotMqttSign(prd_key.data(),dev_name.data(),dev_srt.data(), clientId, username, password); this->m_pwd->setText(password); this->m_id->setText(clientId); this->m_name->setText(username); printf("clientid: %s ", clientId); printf("username: %s ", username); printf("password: %s ", password); }
需要注意的问题为 用的阿里云算法接口中传进去的参数类型为char *,qt QLineEdit空间返回的数据类型为QString 类型,转化方式为借助QByteArray
代码为:
QByteArray prd_key; prd_key.append(this->m_prd_key->text()); QByteArray dev_name; dev_name.append(this->m_dev_name->text()); QByteArray dev_srt; dev_srt.append(this->m_dev_srt->text()); aiotMqttSign(prd_key.data(),dev_name.data(),dev_srt.data(), clientId, username, password);