2016-12-23 2 views
3

Je dois implémenter mon propre HMAC-SHA256 pour l'utiliser dans un projet embarqué. J'ai du mal à le faire fonctionner. Je ne peux même pas obtenir le pseudo code, calculé à la main pour fonctionner, alors je sais que je fais quelque chose de mal!Implémentation HMAC - Pseudo code

Mes calculs de pseduoCode. En suivant le schéma wikipedia

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 

Quand je fais de main calculs pour key = "MyKey" et message = "helloworld" Je reçois le texte suivant:

key = 0x6d796b6579000000000000000000000000000000000000000000000000000000

o_key_pad = 0x31253739255c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c

i_key_pad = 0x5b4f5d534f363636363636363636363636363636363636363636363636363636

hash(i_key_pad ∥ message) = 6fb2e91de7b8b5ec6283846ff7245cd6eb4a4fd26056b529bd42d99fcf3314d2

et le HMAC global de 0d76a16089f85cd2169bb64b6f2c818e6a404a218896483fcd97fee5cce185ae

Répondre

5

Lors de la fixation de la longueur de clé et calulating le rembourrage intérieur et extérieur, vous devez utiliser le blocksize de la fonction de hachage sous-jacente, qui n'est pas la même chose que sa sortie Taille. C'est la taille des blocs d'entrée sur lesquels la fonction fonctionne. Dans le cas de SHA256, la taille de bloc est de 512 bits (64 octets) et la taille de sortie est de 256 bits (32 octets).

Vos résultats sont ce que vous obtenez si vous utilisez 32 comme taille de bloc.

Utilisation de la bonne longueur blocksize la key, o_key_pad et i_key_pad sont fondamentalement les mêmes, seulement deux fois plus longtemps avec queue 00, 5c ou 36 octets respectivement.

Le résultat du hachage interne (c.-à-hash(i_key_pad ∥ message) est:

8bf029764919f9e35249d0d55ffb8fd6c62fe23a85c1515e0120c5005aa813d5 

et la valeur finale (hash(o_key_pad ∥ hash(i_key_pad ∥ message))) est la suivante:.

7fdfaa9c9c0931f52d9ebf2538bc99700f2e771f3af1c1d93945c2256c11aedd 

qui correspond au résultat que je reçois de HMAC la mise en œuvre de OpenSSL

0

Voici le code que j'ai trouvé:

/** 
* 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); 
}