Я хочу реализовать OAuth 1.0
протокол в моем C ++ проекте. Для того чтобы создать подпись OAuth мне нужно реализовать HMAC-SHA1
алгоритм где key
а также text
будет некоторая строка, созданная в соответствии со спецификацией OAuth.
Я хочу использовать библиотеку Crypto ++ для реализации HMAC-SHA1. Я нашел этот пример 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 символами).
Похоже, есть несколько вещей, с которыми вам нужно ознакомиться. (Извините, я не могу помочь, потому что мне никогда не приходилось это делать).
Во-первых, это архитектура безопасности. Вы можете найти некоторые чтения на Руководство для начинающих по OAuth — часть III: архитектура безопасности.
Во-вторых, подпись и формат HMAC-SHA1. Вы можете найти обзор на OAuth Core HMAC-SHA1.
В-третьих, вы должны понимать формат кодирования и представления OAuth. Вы можете найти некоторые чтения на Кодирование основного параметра OAuth.
Чтобы ответить на некоторые ваши вопросы:
Вам нужно будет проанализировать и декодировать параметры, чтобы получить ключ, подписанные данные и подпись. Так что вам нужно будет проанализировать и декодировать три значения: oauth_key
, oauth_data
а также oauth_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, но это относится к 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
Выше используется интерфейс pipline Crypto ++, где данные передаются из источника в приемник. Вы также можете сделать это в стиле «C», используя Put
а также Get
на Base64Decoder
объект:
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());
}
Передо мной стояла очень похожая задача. Сделайте двуногую OAuth 1.0a в C ++. Двуногие, потому что в этом процессе нет пользователя, только клиент и сервер. Как описано в: http://oauth.googlecode.com/svn/spec/ext/consumer_request/1.0/drafts/2/spec.html
Полное подтверждение концепции, включая анализ и декодирование параметров, можно найти по адресу: https://gist.github.com/duedal/a197fc9f6dc1ad59f08c
Должно быть легко основываться на этом, чтобы закончить это. В основном нужно проверить временную метку + nonce, и, конечно, привязать к вашему проекту.