【问题标题】:HMAC Implementation - Pseudo codeHMAC 实现 - 伪代码
【发布时间】:2017-05-09 11:37:18
【问题描述】:

我必须实现自己的 HMAC-SHA256 才能在嵌入式项目中使用。我无法让它工作。我什至无法获得手动计算的伪代码,所以我知道我做错了什么!

我的伪代码计算。按照维基百科中的图表

 1 function hmac (key, message)
 2     if (length(key) > blocksize) then
 3         // keys longer than blocksize are shortened
 4         key = hash(key)
 5     end if
 6     if (length(key) < blocksize) then
 7         // keys shorter than blocksize are zero-padded
 8         key = key ∥ zeroes(blocksize - length(key))
 9     end if
10
11     // Where blocksize is that of the underlying hash function
12     o_key_pad = [0x5c * blocksize] ⊕ key
13     i_key_pad = [0x36 * blocksize] ⊕ key // Where ⊕ is exclusive or (XOR)
14     // Where ∥ is concatenation
15     return hash(o_key_pad ∥ hash(i_key_pad ∥ message))
16 end function

当我手动计算 key="mykey" 和 message="helloworld" 时,我得到以下信息:

key = 0x6d796b6579000000000000000000000000000000000000000000000000000000

o_key_pad = 0x31253739255c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c

i_key_pad = 0x5b4f5d534f363636363636363636363636363636363636363636363636363636

hash(i_key_pad ∥ message) = 6fb2e91de7b8b5ec6283846ff7245cd6eb4a4fd26056b529bd42d99fcf3314d2

0d76a16089f85cd2169bb64b6f2c818e6a404a218896483fcd97fee5cce185ae的整体hmac

【问题讨论】:

    标签: cryptography pseudocode sha256 hmac


    【解决方案1】:

    在固定key长度和计算内外padding时,需要用到底层hash函数的blocksize,和它的output不一样尺寸。这是函数操作的输入块的大小。在 SHA256 的情况下,块大小为 512 位(64 字节),输出大小为 256 位(32 字节)。

    如果你使用 32 作为块大小,你的结果就是你得到的。

    使用正确的长度块大小,keyo_key_padi_key_pad 基本相同,仅是尾随 005c36 字节的两倍。

    内部哈希的结果(即hash(i_key_pad ∥ message)是:

    8bf029764919f9e35249d0d55ffb8fd6c62fe23a85c1515e0120c5005aa813d5
    

    最终的值 (hash(o_key_pad ∥ hash(i_key_pad ∥ message))) 是:

    7fdfaa9c9c0931f52d9ebf2538bc99700f2e771f3af1c1d93945c2256c11aedd
    

    这与我从 OpenSSL 的 HMAC 实现中得到的结果相匹配。

    【讨论】:

      【解决方案2】:

      这是我想出的代码:

       /**
       * This function takes in a key, the length of that key, a message (null terminated) and a pointer to a char[32] or greater array
       * It calculates the HMAC-SHA256 of the given key message combo and returns the resulting code in binary form, 32 hex pairs
      1 @example ???? todo function hmac (key, message)
      2     if (length(key) > blocksize) then
      3         // keys longer than blocksize are shortened
      4         key = hash(key)
      5     end if
      6     if (length(key) < blocksize) then
      7         // keys shorter than blocksize are zero-padded
      8         key = key ∥ zeroes(blocksize - length(key))
      9     end if
      10
      11     // Where blocksize is that of the underlying hash function
      12     o_key_pad = [0x5c * blocksize] ⊕ key
      13     i_key_pad = [0x36 * blocksize] ⊕ key // Where ⊕ is exclusive or (XOR)
      14     // Where ∥ is concatenation
      15     return hash(o_key_pad ∥ hash(i_key_pad ∥ message))
      16 end function
       * @param key todo
       * @param length todo
       * @param message todo
       * @param hmac todo
      */
      void hmac(char key[], int length, char message[], char *hmac){
          int msgLen = strlen(message);   //get the length of the message to be encrypted
          char keyFinal[BLOCK_SIZE] = {0}; //setup array for the data to go into
      
          if(length > BLOCK_SIZE){         //if the given data is too long, hash it
              shaHash(key, keyFinal);
          }
          if(length < BLOCK_SIZE){         //if the given data is too short, pad it with 0x00
              int i;
              for(i = 0; i < BLOCK_SIZE; i++){
                  if(i < length){             //read in the data
                      keyFinal[i] = key[i];
                  }else{                      //if there is no more data to read, read in zeros
                      keyFinal[i] = 0x00;
                  }
              }
          }
          if(length == BLOCK_SIZE){        //if the given data is the right size, transfer it to keyFinal
              int i;
              for(i = 0; i < BLOCK_SIZE; i++){
                  keyFinal[i] = key[i];
              }
          }
      
          char oKeyPad[BLOCK_SIZE] = {0};    //setup the oKeyPad
          char iKeyPad[BLOCK_SIZE] = {0};    //setup the ikeypad
      
          int i;
          for(i = 0; i < BLOCK_SIZE; i++){ //for each item in key final, xor it with O_KEY_PAD and I_KEY_PAD
              oKeyPad[i] = keyFinal[i] ^ O_KEY_PAD;
              iKeyPad[i] = keyFinal[i] ^ I_KEY_PAD;
          }
      
          char iandmesg[BLOCK_SIZE+MAX_SHA];   //setup the inner hash ikeypad concat with message
          char hash_iandmesg[HASH_LEN] = {0};       //get ready to get bytes back from the hashing function
      
          //make the message to be hashed, ikeypad concatinated with message
          for(i = 0; i < BLOCK_SIZE; i++){ //read in ikeypad
              iandmesg[i] = iKeyPad[i];
          }
          for(i = BLOCK_SIZE; i < (msgLen + BLOCK_SIZE); i++){ //read in message
              iandmesg[i] = message[i-BLOCK_SIZE];
          }
      
          shaHash_len(iandmesg, (msgLen+BLOCK_SIZE), hash_iandmesg);   //create the inner hash (ikeypad + message)
      
          char oandihash[(BLOCK_SIZE + HASH_LEN)];    //setup the outter hash, okeypad + (hash of ikeypad + message)
      
          //make the message to be hashed, okeypad concatinated with the hash of (ikeypad + message)
          for(i = 0; i < BLOCK_SIZE; i++){ //read in okeypad
              oandihash[i] = oKeyPad[i];
          }
          for(i = BLOCK_SIZE; i < (BLOCK_SIZE + HASH_LEN); i++){ //read in hash of ikeypad + message
              oandihash[i] = hash_iandmesg[i-BLOCK_SIZE];
          }
      
          //return the result of the hash of (okeypad + hash(ikeypad + message))
          shaHash_len(oandihash, (BLOCK_SIZE + HASH_LEN), hmac);
      }
      

      【讨论】:

        猜你喜欢
        • 2016-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-30
        • 2018-09-10
        • 2021-08-18
        • 2022-01-05
        相关资源
        最近更新 更多