如何在HMAC-SHA1 Crypto ++实现中使用自定义密钥

时间:2013-10-10 16:18:02

标签: c++ oauth crypto++ hmacsha1

我想在我的C ++项目中实现OAuth 1.0协议。为了创建OAuth签名,我需要实现HMAC-SHA1算法,keytext将根据OAuth规范创建一些字符串。

我想使用Crypto ++库来实现HMAC-SHA1。我在项目的wiki上找到了这个HMAC-SHA1示例:

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;

但我无法理解如何使用我创建的key而不是随机生成的字符串。我试过创建:

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

然后出现编译错误。但是,当我写道:

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

然后没有错误。

我需要指定的密钥长度是多少?因为我将拥有不同长度的键(48和96符号)。

2 个答案:

答案 0 :(得分:4)

看来您需要熟悉一些事项。 (对不起,我无法帮助,因为我从来没有这样做过。)

首先是安全架构。您可以在Beginner's Guide to OAuth – Part III : Security Architecture找到一些阅读材料。

其次是HMAC-SHA1签名和格式。您可以在OAuth Core HMAC-SHA1找到概述。

第三,您需要了解OAuth的编码和演示格式。您可以在OAuth Core Parameter Encoding找到一些阅读材料。


回答你的一些问题:

您需要解析和解码参数以获取密钥,签名数据和签名。因此,您需要解析和解码三个值:oauth_keyoauth_dataoauth_signature

然后,您将按如下方式设置Crypto ++ HMAC key

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

之后,您将使用以下内容进行验证:

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;        
}

Crypto ++可能提供帮助的另一件事是Base64解码。以下内容来自HexDecoder wiki page,但它适用于Base64Decoder,因为编码器和解码器使用相同的接口。

string encoded = ...;
string decoded;

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

所以你的代码是:

string encoded = ...;
string decoded;

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

以上使用Crypto ++的pipline接口,其中数据从源流向接收器。您也可以使用Put对象上的GetBase64Decoder以更“C”的方式执行此操作:

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());
}

答案 1 :(得分:0)

我的任务非常相似。在C ++中做两条腿的OAuth 1.0a。两条腿因为没有用户参与该过程,只有客户端和服务器。如:http://oauth.googlecode.com/svn/spec/ext/consumer_request/1.0/drafts/2/spec.html

中所述

完整的概念验证包括解析和解码参数,可在以下网址找到:https://gist.github.com/duedal/a197fc9f6dc1ad59f08c

应该很容易在此基础上完成它。主要需要验证时间戳+ nonce,当然还要绑定到你的项目中。