141 lines
5.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "utils.h"
#include <cassert>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <string>
#include <iomanip>
std::string http::utils::sha256(const std::string &payload) {
return sha256(payload.c_str(), payload.size());
}
std::string http::utils::sha256(const char* data, size_t size) {
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256(reinterpret_cast<const unsigned char *>(data), size, hash);
// Преобразуем хеш в шестнадцатеричную строку
std::stringstream ss;
for (unsigned char i : hash) {
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(i);
}
return ss.str();
}
inline std::string sha256AsB64(const std::string &payload) {
// Вычисляем SHA256 хеш
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256(reinterpret_cast<const unsigned char *>(payload.c_str()), payload.length(), hash);
return http::utils::b64Encode(reinterpret_cast<const char *>(hash), SHA256_DIGEST_LENGTH);
}
static const char b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string http::utils::b64Encode(const char* data, size_t size) {
using ::std::string;
// Use = signs so the end is properly padded.
string retval((((size + 2) / 3) * 4), '=');
::std::size_t outpos = 0;
int bits_collected = 0;
unsigned int accumulator = 0;
for (size_t index = 0; index < size; index++) {
const char i = *(data + index);
accumulator = (accumulator << 8) | (i & 0xff);
bits_collected += 8;
while (bits_collected >= 6) {
bits_collected -= 6;
retval[outpos++] = b64_table[(accumulator >> bits_collected) & 0x3fu];
}
}
if (bits_collected > 0) {
// Any trailing bits that are missing.
assert(bits_collected < 6);
accumulator <<= 6 - bits_collected;
retval[outpos++] = b64_table[accumulator & 0x3fu];
}
assert(outpos >= (retval.size() - 2));
assert(outpos <= retval.size());
return retval;
}
std::string http::utils::b64Encode(const std::string &payload) {
return b64Encode(payload.c_str(), payload.size());
}
std::string http::utils::b64Decode(const std::string &ascdata) {
static const unsigned char reverse_table[128] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64
};
using ::std::string;
string retval;
int bits_collected = 0;
unsigned int accumulator = 0;
for (const auto cd: ascdata) {
const auto c = static_cast<int>(cd);
if (::std::isspace(c) || c == '=') {
// Skip whitespace and padding. Be liberal in what you accept.
continue;
}
if ((c > 127) || (c < 0) || (reverse_table[c] > 63)) {
throw ::std::invalid_argument("This contains characters not legal in a base64 encoded string.");
}
accumulator = (accumulator << 6) | reverse_table[c];
bits_collected += 6;
if (bits_collected >= 8) {
bits_collected -= 8;
retval += static_cast<char>((accumulator >> bits_collected) & 0xffu);
}
}
return retval;
}
std::map<std::string, std::string> http::utils::parseCookies(const std::string& cookieString) {
std::map<std::string, std::string> cookies;
std::istringstream cookieStream(cookieString);
std::string cookie;
while (std::getline(cookieStream, cookie, ';')) {
// Разделяем имя и значение Cookie
size_t equalPos = cookie.find('=');
if (equalPos == std::string::npos) {
continue; // Неверный формат Cookie
}
size_t startIndex = 0;
while (startIndex < cookie.size()) {
if (cookie[startIndex] == '=') {
// некорректная кука, состоит только из пробелов, так что на этом обработку и закончим
return cookies;
}
if (cookie[startIndex] == ' ') {
startIndex++;
} else {
break;
}
}
std::string name = cookie.substr(startIndex, equalPos - startIndex);
std::string value = cookie.substr(equalPos + 1);
// Удаляем пробелы с начала и конца значения Cookie
value.erase(0, value.find_first_not_of(' '));
value.erase(value.find_last_not_of(' ') + 1);
// Добавляем Cookie в map
cookies[name] = value;
}
return cookies;
}