LeeO
LeeO

Reputation: 71

How to create a HMAC 256 using the Crypto++ library?

I have a string which I need to encode in HMAC 256 using C++ and Crypto++. The code from the library wiki:

AutoSeededRandomPool prng;
SecByteBlock key(16);
prng.GenerateBlock(key, key.size());

string plain = "HMAC Test";
string mac, encoded;

/*********************************\
\*********************************/

// Pretty print key
encoded.clear();
StringSource ss1(key, key.size(), true,
    new HexEncoder(
        new StringSink(encoded)
    ) // HexEncoder
); // StringSource

cout << "key: " << encoded << endl;
cout << "plain text: " << plain << endl;

/*********************************\
\*********************************/

try
{
    HMAC< SHA256 > hmac(key, key.size());

    StringSource ss2(plain, true, 
        new HashFilter(hmac,
            new StringSink(mac)
        ) // HashFilter      
    ); // StringSource
}
catch(const CryptoPP::Exception& e)
{
    cerr << e.what() << endl;
    exit(1);
}

/*********************************\
\*********************************/

// Pretty print
encoded.clear();
StringSource ss3(mac, true,
    new HexEncoder(
        new StringSink(encoded)
    ) // HexEncoder
); // StringSource

cout << "hmac: " << encoded << endl;

The example provide works, but seems to do a hell of a lot. All I am trying to do is:

  1. Take a string: "GreatWallOfChina"
  2. key: m2hspk1ZxsjlsDU6JhMvD3TQQhm+zOwab3slKEILoSSnfk3b2+NUyeJiCrRAJ/D3V5y+QDZaIqRx9q9siMopaA==
  3. Convert key to base64: bTJoc3BrMVp4c2psc0RVNkpoTXZEM1RRUWhtK3pPd2FiM3NsS0VJTG9TU25mazNiMitOVXllSmlDclJBSi9EM1Y1eStRRFphSXFSeDlxOXNpTW9wYUE9PQ==
  4. Using that base64 key to create a hmac256.

So, my question is, are all the steps in the example code above necessary? (Byte block declarations, Hex encoding etc)

Apologies if this is a very noobish question.

Upvotes: 1

Views: 5936

Answers (3)

jww
jww

Reputation: 102326

So, my question is, are all the steps in the example code above necessary?

Well, the answer to your question is, mostly YES. But keep in mind the code was written as an example for a wiki.


You may or may not need this. But it seems like you will have a key and a string to input.

AutoSeededRandomPool prng;
SecByteBlock key(16);
prng.GenerateBlock(key, key.size());

string plain = "HMAC Test";
string mac, encoded;

And you probably won't need this if you are not printing it in ASCII:

// Pretty print
encoded.clear();
StringSource ss(mac, true,
    new HexEncoder(
        new StringSink(encoded)
    ) // HexEncoder
); // StringSource

After the code above is removed, the remainder is below, which does not seem excessive to me:

try
{
    HMAC< SHA256 > hmac(key, key.size());

    StringSource ss(plain, true, 
        new HashFilter(hmac,
            new StringSink(mac)
        ) // HashFilter      
    ); // StringSource
}
catch(const CryptoPP::Exception& e)
{
    cerr << e.what() << endl;
    exit(1);
}

Upvotes: 1

Maarten Bodewes
Maarten Bodewes

Reputation: 93998

No, your steps above are certainly not necessary, such as base 64 encoding an already base 64 encoded value.

Crypto++ is mainly based on streaming with sinks and sources. That's just the way the library is set up, but for small calculations it will be somewhat verbose.

Note that most of the sample code is simply key generation and printing out the plaintext, key and authentication tag (MAC value) and some exception handling. The required code is just within the try / catch block basically.

Upvotes: 2

LeeO
LeeO

Reputation: 71

I found someone(woodja) else doing the same thing but for aws:

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;

#include <string>
using std::string;

#include "cryptopp/cryptlib.h"
using CryptoPP::Exception;

#include "cryptopp/hmac.h"
using CryptoPP::HMAC;

#include "cryptopp/sha.h"
using CryptoPP::SHA256;

#include "cryptopp/base64.h"
using CryptoPP::Base64Encoder;

#include "cryptopp/filters.h"
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::HashFilter;

string sign(string key, string plain)
{
        string mac, encoded;
        try
        {
                HMAC< SHA256 > hmac((byte*)key.c_str(), key.length());

                StringSource(plain, true,
                        new HashFilter(hmac,
                                new StringSink(mac)
                        ) // HashFilter      
                ); // StringSource
        }
        catch(const CryptoPP::Exception& e)
        {
                cerr << e.what() << endl;
        }

        encoded.clear();
        StringSource(mac, true,
                new Base64Encoder(
                        new StringSink(encoded)
                ) // Base64Encoder
        ); // StringSource
        std::cout << "encode: " << encoded << endl;
        return encoded;
}

int main()
{
        string mykey = "m2hspk1ZxsjlsDU6JhMvD3TQQhm+zOwab3slKEILoSSnfk3b2+NUyeJiCrRAJ/D3V5y+QDZaIqRx9q9siMopaA==";
        string msg = "GreatWallOfChina";
        std::cout << "key: " << mykey << std::endl;
        std::cout << "msg: " << msg << std::endl;
        sign(mykey,msg);
        return 0;
}

Github answer

Upvotes: 0

Related Questions