1 #ifndef SIMPLE_WEB_CRYPTO_HPP
2 #define SIMPLE_WEB_CRYPTO_HPP
11 #include <openssl/buffer.h>
12 #include <openssl/evp.h>
13 #include <openssl/md5.h>
14 #include <openssl/sha.h>
18 #if _MSC_VER == 1700 // MSVS 2012 has no definition for round()
19 inline double round(
double x) noexcept {
20 return floor(x + 0.5);
25 const static std::size_t buffer_size = 131072;
30 static std::string encode(
const std::string &ascii) noexcept {
34 BUF_MEM *bptr = BUF_MEM_new();
36 b64 = BIO_new(BIO_f_base64());
37 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
38 bio = BIO_new(BIO_s_mem());
40 BIO_set_mem_buf(b64, bptr, BIO_CLOSE);
43 auto base64_length =
static_cast<std::size_t
>(round(4 * ceil(static_cast<double>(ascii.size()) / 3.0)));
44 base64.resize(base64_length);
46 bptr->max = base64_length + 1;
47 bptr->data = &base64[0];
49 if(BIO_write(b64, &ascii[0], static_cast<int>(ascii.size())) <= 0 || BIO_flush(b64) <= 0)
62 static std::string decode(
const std::string &base64) noexcept {
66 ascii.resize((6 * base64.size()) / 8);
69 b64 = BIO_new(BIO_f_base64());
70 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
71 bio = BIO_new_mem_buf(&base64[0], static_cast<int>(base64.size()));
72 bio = BIO_push(b64, bio);
74 auto decoded_length = BIO_read(bio, &ascii[0], static_cast<int>(ascii.size()));
75 if(decoded_length > 0)
76 ascii.resize(static_cast<std::size_t>(decoded_length));
88 std::stringstream hex_stream;
89 hex_stream << std::hex << std::internal << std::setfill(
'0');
90 for(
auto &byte : input)
91 hex_stream << std::setw(2) << static_cast<int>(
static_cast<unsigned char>(byte));
92 return hex_stream.str();
95 static std::string md5(
const std::string &input, std::size_t iterations = 1) noexcept {
99 MD5(reinterpret_cast<const unsigned char *>(&input[0]), input.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
101 for(std::size_t c = 1; c < iterations; ++c)
102 MD5(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
107 static std::string md5(std::istream &stream, std::size_t iterations = 1) noexcept {
110 std::streamsize read_length;
111 std::vector<char> buffer(buffer_size);
112 while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0)
113 MD5_Update(&context, buffer.data(),
static_cast<std::size_t
>(read_length));
115 hash.resize(128 / 8);
116 MD5_Final(reinterpret_cast<unsigned char *>(&hash[0]), &context);
118 for(std::size_t c = 1; c < iterations; ++c)
119 MD5(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
124 static std::string sha1(
const std::string &input, std::size_t iterations = 1) noexcept {
127 hash.resize(160 / 8);
128 SHA1(reinterpret_cast<const unsigned char *>(&input[0]), input.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
130 for(std::size_t c = 1; c < iterations; ++c)
131 SHA1(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
136 static std::string sha1(std::istream &stream, std::size_t iterations = 1) noexcept {
139 std::streamsize read_length;
140 std::vector<char> buffer(buffer_size);
141 while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0)
142 SHA1_Update(&context, buffer.data(),
static_cast<std::size_t
>(read_length));
144 hash.resize(160 / 8);
145 SHA1_Final(reinterpret_cast<unsigned char *>(&hash[0]), &context);
147 for(std::size_t c = 1; c < iterations; ++c)
148 SHA1(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
153 static std::string sha256(
const std::string &input, std::size_t iterations = 1) noexcept {
156 hash.resize(256 / 8);
157 SHA256(reinterpret_cast<const unsigned char *>(&input[0]), input.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
159 for(std::size_t c = 1; c < iterations; ++c)
160 SHA256(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
165 static std::string sha256(std::istream &stream, std::size_t iterations = 1) noexcept {
167 SHA256_Init(&context);
168 std::streamsize read_length;
169 std::vector<char> buffer(buffer_size);
170 while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0)
171 SHA256_Update(&context, buffer.data(),
static_cast<std::size_t
>(read_length));
173 hash.resize(256 / 8);
174 SHA256_Final(reinterpret_cast<unsigned char *>(&hash[0]), &context);
176 for(std::size_t c = 1; c < iterations; ++c)
177 SHA256(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
182 static std::string sha512(
const std::string &input, std::size_t iterations = 1) noexcept {
185 hash.resize(512 / 8);
186 SHA512(reinterpret_cast<const unsigned char *>(&input[0]), input.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
188 for(std::size_t c = 1; c < iterations; ++c)
189 SHA512(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
194 static std::string sha512(std::istream &stream, std::size_t iterations = 1) noexcept {
196 SHA512_Init(&context);
197 std::streamsize read_length;
198 std::vector<char> buffer(buffer_size);
199 while((read_length = stream.read(&buffer[0], buffer_size).gcount()) > 0)
200 SHA512_Update(&context, buffer.data(),
static_cast<std::size_t
>(read_length));
202 hash.resize(512 / 8);
203 SHA512_Final(reinterpret_cast<unsigned char *>(&hash[0]), &context);
205 for(std::size_t c = 1; c < iterations; ++c)
206 SHA512(reinterpret_cast<const unsigned char *>(&hash[0]), hash.size(),
reinterpret_cast<unsigned char *
>(&hash[0]));
212 static std::string
pbkdf2(
const std::string &password,
const std::string &salt,
int iterations,
int key_size) noexcept {
214 key.resize(static_cast<std::size_t>(key_size));
215 PKCS5_PBKDF2_HMAC_SHA1(password.c_str(), password.size(),
216 reinterpret_cast<const unsigned char *
>(salt.c_str()), salt.size(), iterations,
217 key_size,
reinterpret_cast<unsigned char *
>(&key[0]));
static std::string to_hex_string(const std::string &input) noexcept
Return hex string from bytes in input string.
Definition: crypto.h:87
static std::string pbkdf2(const std::string &password, const std::string &salt, int iterations, int key_size) noexcept
key_size is number of bytes of the returned key.
Definition: crypto.h:212