Beispiel #1
0
// https://developer.twitter.com
// /en/docs/basics/authentication/guides/creating-a-signature.html
std::string Network::CalcSignature(
	const std::string &http_method, const std::string &base_url,
	const KeyValue &oauth_param, const KeyValue &query_param,
	const std::string &consumer_secret, const std::string &token_secret)
{
	// "Collecting parameters"
	// percent encode しつつ合成してキーでソートする
	KeyValue param;
	auto encode_insert = [this, &param](const KeyValue &map) {
		for (const auto &entry : map) {
			param.emplace(Escape(entry.first), Escape(entry.second));
		}
	};
	encode_insert(oauth_param);
	encode_insert(query_param);
	// 文字列にする
	// key1=value1&key2=value2&...
	std::string param_str;
	bool is_first = true;
	for (const auto &entry : param) {
		if (is_first) {
			is_first = false;
		}
		else {
			param_str += '&';
		}
		param_str += entry.first;
		param_str += '=';
		param_str += entry.second;
	}

	// "Creating the signature base string"
	// 署名対象
	std::string base = http_method;
	base += '&';
	base += Escape(base_url);
	base += '&';
	base += Escape(param_str);

	// "Getting a signing key"
	// 署名鍵は consumer_secret と token_secret をエスケープして & でつなぐだけ
	std::string key = Escape(consumer_secret);
	key += '&';
	key += Escape(token_secret);

	// "Calculating the signature"
	ShaDigest signature;
	HmacSha1(
		key.data(), key.size(),
		reinterpret_cast<const unsigned char *>(base.data()), base.size(),
		signature);

	return Base64Encode(signature, sizeof(signature));
}
Beispiel #2
0
// https://developer.twitter.com
// /en/docs/basics/authentication/guides/authorizing-a-request
Network::KeyValue Network::CreateOAuthField(
	const std::string &consumer_key, const std::string &access_token)
{
	KeyValue param;

	// oauth_consumer_key: アプリの識別子
	param.emplace("oauth_consumer_key", consumer_key);

	// oauth_nonce: ランダム値
	// OAuth spec ではリプレイ攻撃対策との記述あり
	// 暗号学的安全性は要らない気もするが一応そうしておく
	// Twitter によるとランダムな英数字なら何でもいいらしいが、例に挙げられている
	// 32byte の乱数を BASE64 にして英数字のみを残したものとする
	std::array<uint8_t, 32> nonce;
	for (auto &b : nonce) {
		b = static_cast<uint8_t>(m_secure_rand());
	}
	std::string nonce_b64 = net.Base64Encode(&nonce, sizeof(nonce));
	std::string nonce_str;
	std::copy_if(nonce_b64.begin(), nonce_b64.end(),
		std::back_inserter(nonce_str),
		[](unsigned char c) { return std::isalnum(c); });
	param.emplace("oauth_nonce", nonce_str);

	// 署名は署名以外のフィールドに対しても行うので後で追加する
	// param.emplace("oauth_signature", sha1(...));

	param.emplace("oauth_signature_method", "HMAC-SHA1");
	param.emplace("oauth_timestamp", std::to_string(std::time(nullptr)));
	param.emplace("oauth_token", access_token);
	param.emplace("oauth_version", "1.0");

	return param;
}