views:

348

answers:

4

Hi. I'm trying to implement HMAC-SHA1 algorithm in my C++/Qt application. I have a method for Sha1 algorithm available, I just need to understand the HMAC part of it.

This pseudocode is from 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

What is the blocksize? What does the zeroes-function do on line 8? How do you express lines 12-13 in C++?

+2  A: 

1. What is the blocksize ?

Usually, hash algorithm process data by cutting it into chunks of fixed size data (aka. "blocks"). For SHA1, I the usual block size is 64 bytes.

2. What does the zeros function do on line 8 ?

It (as the comment states) adds "zeroes" to the end of key so that its length matches the "block" size.

3. How do you express lines 12-13 in C++ ?

I think you're looking for the XOR operator: ^.

Example:

o_key_pad = (0x5c * blocksize) ^ key; // Actually, it should be 0x5c5c5c... repeated enough so that it matches key size.

Just a quick note: this has nothing special to do with Qt and you will probably want to do it in "raw" C++ so that you can eventually reuse it in a non-Qt project. Qt is great imho, but you clearly don't require it to implement this.

ereOn
the blocksize is 64 octets (512 bit). And "0x5C * blocksize" is supposed to be a sequence of blocksize many bytes with the value 0x5C
sellibitze
@sellibitze: Thanks. Fixed my answer.
ereOn
A: 

Take at look at the QCA library. It already provides implementations of all major cryptographic algorithms.

lunaryorn
I'm aware of that library, but as I'm in a need of only 1 function, I do not want to incorporate a whole library into my software.
ExplodingRat
A: 

You should also take a look at QCryptographicHash

guruz
QCryptographicHash does not provide HMAC-SHA1 algorithm
ExplodingRat
no, it doesn't. But you can ceartainly make use of it to build your own hmac-sha1
sellibitze
A: 

Here is a function to calculate a HMAC-SHA1 hash of a string:

/**
 * Hashes the given string using the HMAC-SHA1 algorithm.
 *
 * \param key The string to be hashed
 * \param secret The string that contains secret word
 * \return The hashed string
 */
static QString hmac_sha1(const QString &key, const QString &secret)
{
    int text_lenght; // Lenght of the text, that will be hashed
    unsigned char* K; //For secret word.
    int K_lenght; //Lenght of secret word

    K_lenght = secret.size();
    text_lenght = key.size();

    //Need to do for XOR operation. Transforms QString to unsigned char
    std::string tempString = secret.toStdString();
    K = (unsigned char*)tempString.c_str();

    unsigned char ipad[65]; // Inner pad
    unsigned char opad[65]; // Outer pad

    //unsigned char L[20]; //TODO if key > 64 bytes use this to obtain sha1 key

    // Fills ipad and opad with zeros
    bzero( ipad, sizeof ipad);
    bzero( opad, sizeof opad);

    // Copies Secret to ipad and opad
    bcopy( K, ipad, K_lenght);
    bcopy( K, opad, K_lenght);

    // XOR operation for inner and outer pad
    for (int i=0; i<64; i++) {
        ipad[i] ^= 0x36;
        opad[i] ^= 0x5c;
    }

    QByteArray context; // Stores hashed content

    context.append((const char*) ipad,64); // Appends XOR:ed ipad to context
    context.append(key); //Appends key to context

    //Hashes Inner pad
    QByteArray Sha1 = QCryptographicHash::hash(context,
                QCryptographicHash::Sha1);

    context.clear();
    context.append((const char*) opad,64); //Appends opad to context
    context.append(Sha1); //Appends hashed inner pad to context

    Sha1.clear();

    // Hashes outerpad
    Sha1 = QCryptographicHash::hash(context, QCryptographicHash::Sha1);

    // String to return hashed stuff in Base64 format
    QByteArray str(Sha1.toBase64());

    return str;
}
ExplodingRat