华为云IoT设备接入密码C语言生成

华为云IoT设备接入密码C语言生成

Andy 2021-3-18

一、问题

去年给客户(华为SaaS生态链企业,名字匿了)定制了一款高性价比DTU网关,支持协议定制、远程配置、断缓续传。

image.png

有些朋友想拿样品测试,问题来了:

网关接入华为IoT云的参数(ClientId、Username、Password等)一般是从客户的应用后台获取,如果没有后台或者后台对接比较麻烦怎么办?

先看看这些参数是怎么来的:

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

image.png

1. ClientId

(1) 设备ID

① 产品ID

② 设备标识码

(2) 时间戳

2. Username

设备ID

3. Password

由HMACSHA256算法生成

(1) 加密密钥:时间戳

(2) 明文:设备密钥。

以上各个参数中,只有设备标志码每个设备不同,其他均为固定值,即设备与云平台保持一致即可,核心是实现HMACSHA256算法(正好在宇宙四大行做加密谋生-_-||),以下简要分述。

 

二、云平台

客户用自己的华为云账号按以下参数创建产品、注册设备后,不必配置任何参数,网关即可自动上云。

image.png

image.png

image.png

image.png

image.png

 

三、工具生成

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

image.png

 

四、算法检验

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

image.png

 

五、代码生成

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, 435223420@qq.com

// 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;

}

编译,运行。。。

image.png

生成的password完全一致,欧耶~

d52820682c39ed6875c351ddcc1329580de6edd6c9056e6b8190342222f62af1

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值