天天看點

華為雲IoT裝置接入密碼C語言生成

華為雲IoT裝置接入密碼C語言生成

Andy 2021-3-18

一、問題

去年給客戶(華為SaaS生态鍊企業,名字匿了)定制了一款高成本效益DTU網關,支援協定定制、遠端配置、斷緩續傳。

華為雲IoT裝置接入密碼C語言生成

有些朋友想拿樣品測試,問題來了:

網關接入華為IoT雲的參數(ClientId、Username、Password等)一般是從客戶的應用背景擷取,如果沒有背景或者背景對接比較麻煩怎麼辦?

先看看這些參數是怎麼來的:

https://support.huaweicloud.com/api-iothub/iot_06_v5_3009.html

華為雲IoT裝置接入密碼C語言生成

1. ClientId

(1) 裝置ID

① 産品ID

② 裝置辨別碼

(2) 時間戳

2. Username

裝置ID

3. Password

由HMACSHA256算法生成

(1) 加密密鑰:時間戳

(2) 明文:裝置密鑰。

以上各個參數中,隻有裝置标志碼每個裝置不同,其他均為固定值,即裝置與雲平台保持一緻即可,核心是實作HMACSHA256算法(正好在宇宙四大行做加密謀生-_-||),以下簡要分述。

二、雲平台

客戶用自己的華為雲賬号按以下參數建立産品、注冊裝置後,不必配置任何參數,網關即可自動上雲。

華為雲IoT裝置接入密碼C語言生成
華為雲IoT裝置接入密碼C語言生成
華為雲IoT裝置接入密碼C語言生成
華為雲IoT裝置接入密碼C語言生成
華為雲IoT裝置接入密碼C語言生成

三、工具生成

https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/

華為雲IoT裝置接入密碼C語言生成

四、算法檢驗

http://www.jsons.cn/allencrypt/

華為雲IoT裝置接入密碼C語言生成

五、代碼生成

X86平台有openSSL,JAVA有Cipher包,瘦弱的MCU隻能直接用源代碼了,感謝這位大兄弟(不知是不是扒的openSSL源碼?):

https://blog.csdn.net/miniphoenix/article/details/110135164

代碼扒下來精簡了下,輸出由hex改為string,OK~

// HMAC_SHA256.c



#include "HMAC_SHA256.h"

#include "stdint.h"

#include <stdio.h> 

#include <stdlib.h>

#include <string.h>



//------------------------------------------------------------------------------

#define SHA256_BLOCKLEN  64ul //size of message block buffer

#define SHA256_DIGESTLEN 32ul //size of digest in uint8_t

#define SHA256_DIGESTINT 8ul  //size of digest in uint32_t

  

//------------------------------------------------------------------------------

typedef struct sha256_ctx_t

{

  uint64_t len;                 // processed message length

  uint32_t h[SHA256_DIGESTINT]; // hash state

  uint8_t buf[SHA256_BLOCKLEN]; // message block buffer

} SHA256_CTX;

  

void sha256_init(SHA256_CTX *ctx);

void sha256_update(SHA256_CTX *ctx, const uint8_t *m, uint32_t mlen);

// resets state: calls sha256_init

void sha256_final(SHA256_CTX *ctx, uint8_t *md);

  

//------------------------------------------------------------------------------

typedef struct hmac_sha256_ctx_t

{

  uint8_t buf[SHA256_BLOCKLEN]; // key block buffer, not needed after init

  uint32_t h_inner[SHA256_DIGESTINT];

  uint32_t h_outer[SHA256_DIGESTINT];

  SHA256_CTX sha;

} HMAC_SHA256_CTX;

  

void hmac_sha256_init(HMAC_SHA256_CTX *hmac, const uint8_t *key, uint32_t keylen);

void hmac_sha256_update(HMAC_SHA256_CTX *hmac, const uint8_t *m, uint32_t mlen);

// resets state to hmac_sha256_init

void hmac_sha256_final(HMAC_SHA256_CTX *hmac, uint8_t *md);

  

//------------------------------------------------------------------------------

void pbkdf2_sha256(HMAC_SHA256_CTX *ctx,

    const uint8_t *key, uint32_t keylen, const uint8_t *salt, uint32_t saltlen, uint32_t rounds,

    uint8_t *dk, uint32_t dklen);

  

//------------------------------------------------------------------------------

  

#include <string.h>

  

//#define ROR(n,k) ((n >> k) | (n << (32 - k)))

  

static uint32_t ror(uint32_t n, uint32_t k)

{

  return (n >> k) | (n << (32 - k));

}

  

#define ROR(n,k) ror(n,k)

  

#define CH(x,y,z)  (z ^ (x & (y ^ z)))

#define MAJ(x,y,z) ((x & y) | (z & (x | y)))

#define S0(x)      (ROR(x, 2) ^ ROR(x,13) ^ ROR(x,22))

#define S1(x)      (ROR(x, 6) ^ ROR(x,11) ^ ROR(x,25))

#define R0(x)      (ROR(x, 7) ^ ROR(x,18) ^ (x>>3))

#define R1(x)      (ROR(x,17) ^ ROR(x,19) ^ (x>>10))

  

static const uint32_t K[64] =

{

  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,

  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,

  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,

  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,

  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,

  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,

  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,

  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2

};

  

static void sha256_transform(SHA256_CTX *s, const uint8_t *buf)

{

  uint32_t t1, t2, a, b, c, d, e, f, g, h, m[64];

  uint32_t i, j;

   

  for (i = 0, j = 0; i < 16; i++, j += 4)

  {

    m[i] = (uint32_t) buf[j] << 24 | (uint32_t) buf[j + 1] << 16 |

           (uint32_t) buf[j + 2] << 8 | (uint32_t) buf[j + 3];

  }

  for (; i < 64; i++)

  {

    m[i] = R1(m[i - 2]) + m[i - 7] + R0(m[i - 15]) + m[i - 16];

  }

  a = s->h[0];

  b = s->h[1];

  c = s->h[2];

  d = s->h[3];

  e = s->h[4];

  f = s->h[5];

  g = s->h[6];

  h = s->h[7];

  for (i = 0; i < 64; i++)

  {

    t1 = h + S1(e) + CH(e, f, g) + K[i] + m[i];

    t2 = S0(a) + MAJ(a, b, c);

    h = g;

    g = f;

    f = e;

    e = d + t1;

    d = c;

    c = b;

    b = a;

    a = t1 + t2;

  }

  s->h[0] += a;

  s->h[1] += b;

  s->h[2] += c;

  s->h[3] += d;

  s->h[4] += e;

  s->h[5] += f;

  s->h[6] += g;

  s->h[7] += h;

}

  

void sha256_init(SHA256_CTX *s)

{

  s->len = 0;

   

  s->h[0] = 0x6a09e667;

  s->h[1] = 0xbb67ae85;

  s->h[2] = 0x3c6ef372;

  s->h[3] = 0xa54ff53a;

  s->h[4] = 0x510e527f;

  s->h[5] = 0x9b05688c;

  s->h[6] = 0x1f83d9ab;

  s->h[7] = 0x5be0cd19;

}

  

void sha256_final(SHA256_CTX *s, uint8_t *md)

{

  uint32_t r = s->len % SHA256_BLOCKLEN;

  int i;

   

  //pad

  s->buf[r++] = 0x80;

  if (r > 56)

  {

    memset(s->buf + r, 0, SHA256_BLOCKLEN - r);

    r = 0;

    sha256_transform(s, s->buf);

  }

  memset(s->buf + r, 0, 56 - r);

  s->len *= 8;

  s->buf[56] = s->len >> 56;

  s->buf[57] = s->len >> 48;

  s->buf[58] = s->len >> 40;

  s->buf[59] = s->len >> 32;

  s->buf[60] = s->len >> 24;

  s->buf[61] = s->len >> 16;

  s->buf[62] = s->len >> 8;

  s->buf[63] = s->len;

  sha256_transform(s, s->buf);

   

  for (i = 0; i < SHA256_DIGESTINT; i++)

  {

    md[4 * i    ] = s->h[i] >> 24;

    md[4 * i + 1] = s->h[i] >> 16;

    md[4 * i + 2] = s->h[i] >> 8;

    md[4 * i + 3] = s->h[i];

  }

  sha256_init(s);

}

  

void sha256_update(SHA256_CTX *s, const uint8_t *m, uint32_t len)

{

  const uint8_t *p = m;

  uint32_t r = s->len % SHA256_BLOCKLEN;

   

  s->len += len;

  if (r)

  {

    if (len + r < SHA256_BLOCKLEN)

    {

      memcpy(s->buf + r, p, len);

      return;

    }

    memcpy(s->buf + r, p, SHA256_BLOCKLEN - r);

    len -= SHA256_BLOCKLEN - r;

    p += SHA256_BLOCKLEN - r;

    sha256_transform(s, s->buf);

  }

  for (; len >= SHA256_BLOCKLEN; len -= SHA256_BLOCKLEN, p += SHA256_BLOCKLEN)

  {

    sha256_transform(s, p);

  }

  memcpy(s->buf, p, len);

}

  

#define INNER_PAD '\x36'

#define OUTER_PAD '\x5c'

  

void hmac_sha256_init(HMAC_SHA256_CTX *hmac, const uint8_t *key, uint32_t keylen)

{

  SHA256_CTX *sha = &hmac->sha;

  uint32_t i;

   

  if (keylen <= SHA256_BLOCKLEN)

  {

    memcpy(hmac->buf, key, keylen);

    memset(hmac->buf + keylen, '\0', SHA256_BLOCKLEN - keylen);

  }

  else

  {

    sha256_init(sha);

    sha256_update(sha, key, keylen);

    sha256_final(sha, hmac->buf);

    memset(hmac->buf + SHA256_DIGESTLEN, '\0', SHA256_BLOCKLEN - SHA256_DIGESTLEN);

  }

   

  for (i = 0; i < SHA256_BLOCKLEN; i++)

  {

    hmac->buf[ i ] = hmac->buf[ i ] ^ OUTER_PAD;

  }

   

  sha256_init(sha);

  sha256_update(sha, hmac->buf, SHA256_BLOCKLEN);

  // copy outer state

  memcpy(hmac->h_outer, sha->h, SHA256_DIGESTLEN);

   

  for (i = 0; i < SHA256_BLOCKLEN; i++)

  {

    hmac->buf[ i ] = (hmac->buf[ i ] ^ OUTER_PAD) ^ INNER_PAD;

  }

   

  sha256_init(sha);

  sha256_update(sha, hmac->buf, SHA256_BLOCKLEN);

  // copy inner state

  memcpy(hmac->h_inner, sha->h, SHA256_DIGESTLEN);

}

  

void hmac_sha256_update(HMAC_SHA256_CTX *hmac, const uint8_t *m, uint32_t mlen)

{

  sha256_update(&hmac->sha, m, mlen);

}

  

void hmac_sha256_final(HMAC_SHA256_CTX *hmac, uint8_t *md)

{

  SHA256_CTX *sha = &hmac->sha;

  sha256_final(sha, md);

   

  // reset sha to outer state

  memcpy(sha->h, hmac->h_outer, SHA256_DIGESTLEN);

  sha->len = SHA256_BLOCKLEN;

   

  sha256_update(sha, md, SHA256_DIGESTLEN);

  sha256_final(sha, md); // md = D(outer || D(inner || msg))

   

  // reset sha to inner state -> reset hmac

  memcpy(sha->h, hmac->h_inner, SHA256_DIGESTLEN);

  sha->len = SHA256_BLOCKLEN;

}

  

void pbkdf2_sha256(HMAC_SHA256_CTX *hmac,

    const uint8_t *key, uint32_t keylen, const uint8_t *salt, uint32_t saltlen, uint32_t rounds,

    uint8_t *dk, uint32_t dklen)

{

  uint8_t *U;

  uint8_t *T;

  uint8_t count[4];

  uint32_t i, j, k;

  uint32_t len;

  

  uint32_t hlen = SHA256_DIGESTLEN;

  uint32_t l = dklen / hlen + ((dklen % hlen) ? 1 : 0);

  uint32_t r = dklen - (l - 1) * hlen;

   

  hmac_sha256_init(hmac, key, keylen);

   

  U = hmac->buf;

  T = dk;

   

  len = hlen;

  for (i = 1; i <= l; i++)

  {

    if (i == l) { len = r; }

    count[0] = (i >> 24) & 0xFF;

    count[1] = (i >> 16) & 0xFF;

    count[2] = (i >>  8) & 0xFF;

    count[3] = (i) & 0xFF;

    hmac_sha256_update(hmac, salt, saltlen);

    hmac_sha256_update(hmac, count, 4);

    hmac_sha256_final(hmac, U);

    memcpy(T, U, len);

    for (j = 1; j < rounds; j++)

    {

      hmac_sha256_update(hmac, U, hlen);

      hmac_sha256_final(hmac, U);

      for (k = 0; k < len; k++)

      {

        T[k] ^= U[k];

      }

    }

    T += len;

  }

   

}



void compute_sha_ex(unsigned char* dest, const uint8_t *msg, uint32_t mlen)

{

  uint8_t md[SHA256_DIGESTLEN] = {0};

  SHA256_CTX sha;

  sha256_init(&sha);

  sha256_update(&sha, msg, mlen);

  sha256_final(&sha, md);

  memcpy(dest, md, SHA256_DIGESTLEN);

}

  

void compute_hmac_ex(unsigned char* dest, const uint8_t *key, uint32_t klen, const uint8_t *msg, uint32_t mlen)

{

  uint8_t md[SHA256_DIGESTLEN] = {0};

  HMAC_SHA256_CTX hmac;



  hmac_sha256_init  (&hmac, key, klen);

  hmac_sha256_update(&hmac, msg, mlen);

  hmac_sha256_final (&hmac, md);



#if 0   // hex value

  memcpy(dest, md, SHA256_DIGESTLEN);

#else   // string of hex value

  for (int i = 0; i < SHA256_DIGESTLEN; i++)

  {

    sprintf(dest, "%s%02x", dest, md[i]);

  }

#endif

}
           
// HMAC_SHA256.h

#ifndef _HMAC_SHA256_H
#define _HMAC_SHA256_H

#ifndef uint8_t
  typedef unsigned char   uint8_t;
#endif

#ifndef uint32_t
  typedef unsigned int    uint32_t;
#endif

void compute_hmac_ex(unsigned char* dest, const uint8_t *key, uint32_t klen, const uint8_t *msg, uint32_t mlen);

#endif
           
// HuaweiIotToken.c

// Andy 18676383370, [email protected]

// https://support.huaweicloud.com/api-iothub/iot_06_v5_3009.html



#include "HuaweiIotToken.h"  

#include "HMAC_SHA256.h"  

#include <stdio.h> 

#include <string.h>



#define TIME_STAMP_LEN            (10)



int TOKEN_GetDeviceId(const uchar *productId, const uchar *deviceCode, uchar *deviceId)

{

  if ( !productId )

  {

    printf("[%s] input error: productId is NULL", __FUNCTION__);

    return -10;

  }

  if ( !strlen(productId) )

  {

    printf("[%s] input error: productId is empty", __FUNCTION__);

    return -11;

  }

  if ( !deviceCode )

  {

    printf("[%s] input error: deviceCode is NULL", __FUNCTION__);

    return -20;

  }

  if ( !strlen(deviceCode) )

  {

    printf("[%s] input error: deviceCode is empty", __FUNCTION__);

    return -21;

  }

  if ( !deviceId )

  {

    printf("[%s] input error: deviceId is NULL", __FUNCTION__);

    return -30;

  }

   

  sprintf(deviceId, "%s_%s", productId, deviceCode);



  return 0;

}



int TOKEN_GetClientId(const uchar *deviceId, const uchar *timeStamp, uchar *clientId)

{

  const uchar DEVICE_ID_TYPE[1+1]   = "0";

  const uchar CIPHER_SIGN_TYPE[1+1] = "0";



  if ( !deviceId )

  {

    printf("[%s] input error: productId is NULL", __FUNCTION__);

    return -10;

  }

  if ( !strlen(deviceId) )

  {

    printf("[%s] input error: productId is empty", __FUNCTION__);

    return -11;

  }

  if ( !timeStamp )

  {

    printf("[%s] input error: timeStamp is NULL", __FUNCTION__);

    return -20;

  }

  if ( strlen(timeStamp) != TIME_STAMP_LEN )

  {

    printf("[%s] input error: timeStamp len %d", __FUNCTION__, strlen(timeStamp));

    return -21;

  }

  if ( !clientId )

  {

    printf("[%s] input error: deviceCode is NULL", __FUNCTION__);

    return -30;

  }



  sprintf(clientId, "%s_%s_%s_%s",

                    deviceId,

                    DEVICE_ID_TYPE,

                    CIPHER_SIGN_TYPE,

                    timeStamp);



  return 0;

}



int TOKEN_GetPassword(const uchar *timeStamp, const uchar *deviceSecret, uchar *password)

{

  if ( !timeStamp )

  {

    printf("[%s] input error: timeStamp is NULL", __FUNCTION__);

    return -10;

  }

  if ( strlen(timeStamp) != TIME_STAMP_LEN )

  {

    printf("[%s] input error: timeStamp len %d", __FUNCTION__, strlen(timeStamp));

    return -11;

  }

  if ( !deviceSecret )

  {

    printf("[%s] input error: deviceSecret is NULL", __FUNCTION__);

    return -20;

  }

  if ( !strlen(deviceSecret) )

  {

    printf("[%s] input error: deviceSecret is empty", __FUNCTION__);

    return -21;

  }

  if ( !password )

  {

    printf("[%s] input error: password is NULL", __FUNCTION__);

    return -30;

  }



  compute_hmac_ex(  password,

                    timeStamp,

                    strlen(timeStamp),

                    deviceSecret,

                    strlen(deviceSecret)  );

   

  return 0;

}
           
// HuaweiIotToken.h



#ifndef _HUAWEI_IOT_TOKEN_H

#define _HUAWEI_IOT_TOKEN_H



#ifndef uchar

  typedef unsigned char   uchar;

#endif



int TOKEN_GetDeviceId(const uchar *productId, const uchar *deviceCode,   uchar *deviceId);

int TOKEN_GetClientId(const uchar *deviceId,  const uchar *timeStamp,    uchar *clientId);

int TOKEN_GetPassword(const uchar *timeStamp, const uchar *deviceSecret, uchar *password);



#endif
           
// test.c



#include "HuaweiIotToken.h"

#include <stdio.h>



#define MAX_STR_LEN               (256)



#define CLIENT_ID_LEN             (256)

#define USERNAME_LEN              (256)

#define PASSWORD_LEN              (256)



#define PRODUCT_ID                "myProductId"

#define IMEI                      "864424044187240"

#define DEVICE_SECRET             "12345678"

#define DEVICE_REG_TIME_STAMP     "2021031803"



int main(int argc,char **argv)  

{

  int ret = 0;



  uchar deviceId[MAX_STR_LEN + 1]   = {0};

  ret = TOKEN_GetDeviceId(PRODUCT_ID, IMEI, deviceId);

  if ( ret ) return -1;

  printf("product id  : %s\n", PRODUCT_ID);

  printf("device code : %s\n", IMEI);

  printf("device id   : %s\n", deviceId);

  printf("\n");



  uchar clientId[CLIENT_ID_LEN + 1] = {0};

  ret = TOKEN_GetClientId(deviceId, DEVICE_REG_TIME_STAMP, clientId);

  if ( ret ) return -2;

  printf("device id   : %s\n", deviceId);

  printf("time stamp  : %s\n", DEVICE_REG_TIME_STAMP);

  printf("client id   : %s\n", clientId);

  printf("\n");



  uchar password[PASSWORD_LEN + 1] = {0};

  ret = TOKEN_GetPassword(DEVICE_REG_TIME_STAMP, DEVICE_SECRET, password);

  if ( ret ) return -3;

  printf("timeStamp   : %s\n", DEVICE_REG_TIME_STAMP);

  printf("deviceSecret: %s\n", DEVICE_SECRET);

  printf("password    : %s\n", password);

  printf("\n");



  return 0;

}
           

編譯,運作。。。

華為雲IoT裝置接入密碼C語言生成

生成的password完全一緻,歐耶~

d52820682c39ed6875c351ddcc1329580de6edd6c9056e6b8190342222f62af1

繼續閱讀