Question

I want to implement OAuth 1.0 protocol in my C++ project. In order to create OAuth signature I need to implement HMAC-SHA1 algorithm where key and text will be some string created according to OAuth specification.

I want to use Crypto++ library for implementing HMAC-SHA1. I found this HMAC-SHA1 example on wiki of project:

AutoSeededRandomPool prng;

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

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

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

// Pretty print key
encoded.clear();
StringSource(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(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(mac, true,
    new HexEncoder(
        new StringSink(encoded)
    ) // HexEncoder
); // StringSource

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

But I can't understand how instead of random generated string use my created key. I tried just create:

string key=...; //string generated by OAuth specification;

But then appear compiling errors. However when I write:

string plain=...; //string generated by OAuth specification;

Then there is no errors.

And what key length I need to specify? Because I will have keys of different lengths (with 48 and maybe 96 symbols).

Was it helpful?

Solution

It appears there are a few things you need to get familiar with. (Sorry I can't help because I've never had to do it).

First is the Security Architecture. You can find some reading at Beginner's Guide to OAuth – Part III : Security Architecture.

Second is the HMAC-SHA1 signature and format. You can find the overview at OAuth Core HMAC-SHA1.

Third, you need to understand OAuth's encoding and presentation format. You can find some reading at OAuth Core Parameter Encoding.


To answer some of your questions:

You will need to parse and decode the parameters to get the key, signed data, and signature. So you will need to parse and decode three values: oauth_key, oauth_data and oauth_signature.

Then, you will set up your Crypto++ HMAC key as follows.

SecByteBlock key(SHA1::BLOCKSIZE);
memcpy(key.data(), key.size(), oauth_key);

After that, you would verify with the following:

byte oauth_key[] = ...; // Your parsed and decoded key
string oauth_data = ...; // Your parsed and decoded data
string oauth_signature = ...; // // Your parsed and decoded signature

try
{
    SecByteBlock key(SHA1::BLOCKSIZE);
    memcpy(key.data(), key.size(), oauth_key);

    HMAC< SHA1 > hmac(key, key.size());
    const int flags = HashVerificationFilter::THROW_EXCEPTION | HashVerificationFilter::HASH_AT_END;

    StringSource ss(oauth_data + oauth_signature + mac, true, 
        new HashVerificationFilter(hmac, NULL, flags)
    ); // StringSource

    cout << "Verified message" << endl;
}
catch(const CryptoPP::Exception& e)
{
    // Handle failure
    cerr << e.what() << endl;        
}

Another thing Crypto++ might be able to help with is Base64 decoding. Below is from the HexDecoder wiki page, but it applies to Base64Decoder because the encoders and decoders use the same interface.

string encoded = ...;
string decoded;

StringSource ss(encoded,
    new HexDecoder(
        new StringSink(decoded)
    ) // HexDecoder
); // StringSource

So your code would be:

string encoded = ...;
string decoded;

StringSource ss(encoded,
    new Base64Decoder(
        new StringSink(decoded)
    ) // Base64Decoder
); // StringSource

The above uses Crypto++'s pipline interface, where data flows from a source to a sink. You can also do it in a more "C" like manner using Put and Get on the Base64Decoder object:

string encoded = ...;
string decoded;

Base64Decoder decoder;

decoder.Put( (byte*)encoded.data(), encoded.size() );
decoder.MessageEnd();

word64 size = decoder.MaxRetrievable();
if(size && size <= SIZE_MAX)
{
    decoded.resize(size);       
    decoder.Get((byte*)decoded.data(), decoded.size());
}

OTHER TIPS

I was tasked with a very similar task. Do two-legged OAuth 1.0a in C++. Two-legged because there is no user involved in the process, only the client and the server. As described in: http://oauth.googlecode.com/svn/spec/ext/consumer_request/1.0/drafts/2/spec.html

The complete proof of concept including parsing and decoding the parameters can be found at: https://gist.github.com/duedal/a197fc9f6dc1ad59f08c

Should be easy to build on this to complete it. Mainly need to validate the timestamp+nonce, and of course tie into your project.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top