阿里云的物联网平台设备端使用mqtt时必须要使用阿里云加密算法通过设备三元组算出来的username、password、clientId才可以连接成功

使用mqtt.fx、mqttBox等客户端软件时必须要根据设备三元组计算出正确的登录信息,最近在使用qt,所以使用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  * \brief          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\n", 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\n", clientId);
    printf("username: %s\n", username);
    printf("password: %s\n", 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);