| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- /**
- * Copyright (c) 2017 Baidu.com, Inc. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
- * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- *
- * @author baidu aip
- */
- #ifndef __AIP_UTILS_H__
- #define __AIP_UTILS_H__
- #include <string>
- #include <fstream>
- #include <ctype.h>
- #include <openssl/evp.h>
- #include <openssl/hmac.h>
- #include <algorithm>
- #include <openssl/md5.h>
- const int __BCE_VERSION__ = 1;
- const int __BCE_EXPIRE__ = 1800;
- namespace aip {
-
- template<class CharT, class Traits, class Allocator>
- std::basic_istream<CharT, Traits>& getall(std::basic_istream<CharT, Traits>& input,
- std::basic_string<CharT, Traits, Allocator>& str) {
- std::ostringstream oss;
- oss << input.rdbuf();
- str.assign(oss.str());
- return input;
- }
-
- inline int get_file_content(const char *filename, std::string* out) {
- std::ifstream in(filename, std::ios::in | std::ios::binary);
- if (in) {
- getall(in, *out);
- return 0;
- } else {
- return -1;
- }
- }
-
- inline std::string to_upper(std::string src)
- {
- std::transform(src.begin(), src.end(), src.begin(), toupper);
- return src;
- }
-
-
- inline std::string to_lower(std::string src)
- {
- std::transform(src.begin(), src.end(), src.begin(), tolower);
- return src;
- }
-
- inline std::string to_hex(unsigned char c, bool lower = false)
- {
- const std::string hex = "0123456789ABCDEF";
-
- std::stringstream ss;
- ss << hex[c >> 4] << hex[c & 0xf];
-
- return lower ? to_lower(ss.str()) : ss.str();
- }
-
- inline time_t now()
- {
- return time(NULL);
- }
-
- std::string utc_time(time_t timestamp)
- {
- struct tm result_tm;
- char buffer[32];
-
- #ifdef _WIN32
- gmtime_s(&result_tm, ×tamp);
- #else
- gmtime_r(×tamp, &result_tm);
- #endif
-
- size_t size = strftime(buffer, 32, "%Y-%m-%dT%H:%M:%SZ", &result_tm);
-
- return std::string(buffer, size);
- }
-
- void url_parse(
- const std::string & url,
- std::map<std::string, std::string> & params)
- {
- int pos = (int)url.find("?");
- if (pos != -1)
- {
- int key_start = pos + 1,
- key_len = 0,
- val_start = 0;
- for (int i = key_start; i <= (int)url.size(); ++i)
- {
- switch (url[i])
- {
- case '=':
- key_len = i - key_start;
- val_start = i + 1;
- break;
- case '\0':
- case '&':
- if (key_len != 0)
- {
- params[url.substr(key_start, key_len)] = url.substr(val_start, i - val_start);
- key_start = i + 1;
- key_len = 0;
- }
- break;
- default:
- break;
- }
- }
- }
- }
-
- std::string url_encode(const std::string & input, bool encode_slash=true)
- {
- std::stringstream ss;
- const char *str = input.c_str();
-
- for (uint32_t i = 0; i < input.size(); i++)
- {
- unsigned char c = str[i];
- if (isalnum(c) || c == '_' || c == '-' || c == '~' || c == '.' || (!encode_slash && c == '/'))
- {
- ss << c;
- }
- else
- {
- ss << "%" << to_hex(c);
- }
- }
-
- return ss.str();
- }
-
- std::string canonicalize_params(std::map<std::string, std::string> & params)
- {
- std::vector<std::string> v;
- v.reserve(params.size());
-
- for (auto & it : params) {
- v.push_back(url_encode(it.first) + "=" + url_encode(it.second));
- }
- std::sort(v.begin(), v.end());
-
- std::string result;
- for (auto & it : v)
- {
- result.append((result.empty() ? "" : "&") + it);
- }
- return result;
- }
-
- std::string canonicalize_headers(std::map<std::string, std::string> & headers)
- {
- std::vector<std::string> v;
- v.reserve(headers.size());
-
- for (auto & it : headers) {
- v.push_back(url_encode(to_lower(it.first)) + ":" + url_encode(it.second));
- }
- std::sort(v.begin(), v.end());
-
- std::string result;
- for (auto & it : v)
- {
- result.append((result.empty() ? "" : "\n") + it);
- }
- return result;
- }
-
- std::string get_headers_keys(std::map<std::string, std::string> & headers)
- {
- std::vector<std::string> v;
- v.reserve(headers.size());
-
- for (auto & it : headers) {
- v.push_back(to_lower(it.first));
- }
-
- std::string result;
- for (auto & it : v)
- {
- result.append((result.empty() ? "" : ";") + it);
- }
- return result;
- }
-
- std::string get_host(const std::string & url)
- {
- int pos = (int)url.find("://") + 3;
- return url.substr(
- pos,
- url.find('/', pos) - pos
- );
- }
-
-
- std::string get_path(const std::string & url)
- {
- int path_start = (int)url.find('/', url.find("://") + 3);
- int path_end = (int)url.find('?');
- path_end = path_end == -1 ? (int)url.size() : path_end;
-
- return url.substr(path_start, path_end - path_start);
- }
-
- std::string hmac_sha256(
- const std::string & src,
- const std::string & sk)
- {
- const EVP_MD *evp_md = EVP_sha256();
- unsigned char md[EVP_MAX_MD_SIZE];
- unsigned int md_len = 0;
-
- if (HMAC(evp_md,
- reinterpret_cast<const unsigned char *>(sk.data()), (int)sk.size(),
- reinterpret_cast<const unsigned char *>(src.data()), src.size(),
- md, &md_len) == NULL)
- {
- return "";
- }
-
- std::stringstream ss;
- for (int i = 0; i < (int)md_len; ++i)
- {
- ss << to_hex(md[i], true);
- }
-
- return ss.str();
- }
-
- void sign(
- std::string method,
- std::string & url,
- std::map<std::string, std::string> & params,
- std::map<std::string, std::string> & headers,
- std::string & ak,
- std::string & sk)
- {
- url_parse(url, params);
- headers["Host"] = get_host(url);
- std::string timestamp = utc_time(now());
- headers["x-bce-date"] = timestamp;
-
- std::stringstream ss;
- ss << "bce-auth-v" << __BCE_VERSION__ << "/" << ak << "/"
- << timestamp << "/" << __BCE_EXPIRE__;
-
- std::string val = ss.str();
- std::string sign_key = hmac_sha256(val, sk);
-
- ss.str("");
- ss << to_upper(method) << '\n' << url_encode(get_path(url), false)
- << '\n' << canonicalize_params(params)
- << '\n' << canonicalize_headers(headers);
-
- std::string signature = hmac_sha256(ss.str(), sign_key);
-
- ss.str("");
- ss << "bce-auth-v" << __BCE_VERSION__ << "/" << ak << "/"
- << timestamp << "/" << __BCE_EXPIRE__ << "/"
- << get_headers_keys(headers) << "/" << signature;
-
- headers["authorization"] = ss.str();
- }
-
- }
- #endif
|