11 //Moving these to a seperate namespace for minimal global namespace cluttering does not work with clang++
12 #include <openssl/evp.h>
13 #include <openssl/buffer.h>
14 #include <openssl/sha.h>
15 #include <openssl/md5.h>
18 //TODO 2017: remove workaround for MSVS 2012
19 #if _MSC_VER == 1700 //MSVS 2012 has no definition for round()
20 inline double round(double x) { //custom definition of round() for positive numbers
21 return floor(x + 0.5);
26 const static size_t buffer_size=131072;
30 static std::string encode(const std::string &ascii) {
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);
42 //Write directly to base64-buffer to avoid copy
43 int base64_length=static_cast<int>(round(4*ceil((double)ascii.size()/3.0)));
44 base64.resize(base64_length);
46 bptr->max=base64_length+1;
47 bptr->data=(char*)&base64[0];
49 BIO_write(b64, &ascii[0], static_cast<int>(ascii.size()));
52 //To keep &base64[0] through BIO_free_all(b64)
62 static std::string decode(const std::string &base64) {
65 //Resize ascii, however, the size is a up to two bytes too large.
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((char*)&base64[0], static_cast<int>(base64.size()));
72 bio = BIO_push(b64, bio);
74 int decoded_length = BIO_read(bio, &ascii[0], static_cast<int>(ascii.size()));
75 ascii.resize(decoded_length);
83 /// Return hex string from bytes in input string.
84 static std::string to_hex_string(const std::string &input) {
85 std::stringstream hex_stream;
86 hex_stream << std::hex << std::internal << std::setfill('0');
87 for (auto &byte : input)
88 hex_stream << std::setw(2) << static_cast<int>(static_cast<unsigned char>(byte));
89 return hex_stream.str();
92 static std::string md5(const std::string &input, size_t iterations=1) {
96 MD5(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
98 for (size_t c = 1; c < iterations; ++c)
99 MD5(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
104 static std::string md5(std::istream &stream, size_t iterations=1) {
107 std::streamsize read_length;
108 std::vector<char> buffer(buffer_size);
109 while((read_length=stream.read(&buffer[0], buffer_size).gcount())>0)
110 MD5_Update(&context, buffer.data(), read_length);
112 hash.resize(128 / 8);
113 MD5_Final(reinterpret_cast<unsigned char*>(&hash[0]), &context);
115 for (size_t c = 1; c < iterations; ++c)
116 MD5(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
121 static std::string sha1(const std::string &input, size_t iterations=1) {
124 hash.resize(160 / 8);
125 SHA1(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
127 for (size_t c = 1; c < iterations; ++c)
128 SHA1(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
133 static std::string sha1(std::istream &stream, size_t iterations=1) {
136 std::streamsize read_length;
137 std::vector<char> buffer(buffer_size);
138 while((read_length=stream.read(&buffer[0], buffer_size).gcount())>0)
139 SHA1_Update(&context, buffer.data(), read_length);
141 hash.resize(160 / 8);
142 SHA1_Final(reinterpret_cast<unsigned char*>(&hash[0]), &context);
144 for (size_t c = 1; c < iterations; ++c)
145 SHA1(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
150 static std::string sha256(const std::string &input, size_t iterations=1) {
153 hash.resize(256 / 8);
154 SHA256(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
156 for (size_t c = 1; c < iterations; ++c)
157 SHA256(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
162 static std::string sha256(std::istream &stream, size_t iterations=1) {
164 SHA256_Init(&context);
165 std::streamsize read_length;
166 std::vector<char> buffer(buffer_size);
167 while((read_length=stream.read(&buffer[0], buffer_size).gcount())>0)
168 SHA256_Update(&context, buffer.data(), read_length);
170 hash.resize(256 / 8);
171 SHA256_Final(reinterpret_cast<unsigned char*>(&hash[0]), &context);
173 for (size_t c = 1; c < iterations; ++c)
174 SHA256(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
179 static std::string sha512(const std::string &input, size_t iterations=1) {
182 hash.resize(512 / 8);
183 SHA512(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
185 for (size_t c = 1; c < iterations; ++c)
186 SHA512(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
191 static std::string sha512(std::istream &stream, size_t iterations=1) {
193 SHA512_Init(&context);
194 std::streamsize read_length;
195 std::vector<char> buffer(buffer_size);
196 while((read_length=stream.read(&buffer[0], buffer_size).gcount())>0)
197 SHA512_Update(&context, buffer.data(), read_length);
199 hash.resize(512 / 8);
200 SHA512_Final(reinterpret_cast<unsigned char*>(&hash[0]), &context);
202 for (size_t c = 1; c < iterations; ++c)
203 SHA512(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
208 /// key_size is number of bytes of the returned key.
209 static std::string pbkdf2(const std::string &password, const std::string &salt, int iterations, int key_size) {
211 key.resize(key_size);
212 PKCS5_PBKDF2_HMAC_SHA1(password.c_str(), password.size(),
213 reinterpret_cast<const unsigned char*>(salt.c_str()), salt.size(), iterations,
214 key_size, reinterpret_cast<unsigned char*>(&key[0]));
219 #endif /* CRYPTO_HPP */