Welcome to mirror list, hosted at ThFree Co, Russian Federation.

crypto.hpp - github.com/marian-nmt/Simple-WebSocket-Server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 366b6cd4c27073901ca8b25560e3b335114dd374 (plain)
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#ifndef CRYPTO_HPP
#define	CRYPTO_HPP

#include <string>
#include <cmath>
#include <sstream>
#include <iomanip>

//Moving these to a seperate namespace for minimal global namespace cluttering does not work with clang++
#include <openssl/evp.h>
#include <openssl/buffer.h>
#include <openssl/sha.h>
#include <openssl/md5.h>

namespace SimpleWeb {
    //TODO 2017: remove workaround for MSVS 2012
    #if _MSC_VER == 1700 //MSVS 2012 has no definition for round()
        inline double round(double x) { //custom definition of round() for positive numbers
            return floor(x + 0.5);
        }
    #endif

    class Crypto {
    public:
        class Base64 {
        public:
            static std::string encode(const std::string &ascii) {
                std::string base64;
                
                BIO *bio, *b64;
                BUF_MEM *bptr=BUF_MEM_new();

                b64 = BIO_new(BIO_f_base64());
                BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
                bio = BIO_new(BIO_s_mem());
                BIO_push(b64, bio);
                BIO_set_mem_buf(b64, bptr, BIO_CLOSE);
                
                //Write directly to base64-buffer to avoid copy
                int base64_length=static_cast<int>(round(4*ceil((double)ascii.size()/3.0)));
                base64.resize(base64_length);
                bptr->length=0;
                bptr->max=base64_length+1;
                bptr->data=(char*)&base64[0];

                BIO_write(b64, &ascii[0], static_cast<int>(ascii.size()));
                BIO_flush(b64);

                //To keep &base64[0] through BIO_free_all(b64)
                bptr->length=0;
                bptr->max=0;
                bptr->data=nullptr;

                BIO_free_all(b64);
                
                return base64;
            }
            
            static std::string decode(const std::string &base64) {
                std::string ascii;
                
                //Resize ascii, however, the size is a up to two bytes too large.
                ascii.resize((6*base64.size())/8);
                BIO *b64, *bio;

                b64 = BIO_new(BIO_f_base64());
                BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
                bio = BIO_new_mem_buf((char*)&base64[0], static_cast<int>(base64.size()));
                bio = BIO_push(b64, bio);

                int decoded_length = BIO_read(bio, &ascii[0], static_cast<int>(ascii.size()));
                ascii.resize(decoded_length);

                BIO_free_all(b64);
                
                return ascii;
            }
        };
        
        /// Return hex string from bytes in input string.
        static std::string to_hex_string(const std::string &input) {
          std::stringstream hex_stream;
          hex_stream << std::hex << std::internal << std::setfill('0');
          for (auto &byte : input)
            hex_stream << std::setw(2) << static_cast<int>(static_cast<unsigned char>(byte));
          return hex_stream.str();
        }
        
        static std::string md5(const std::string &input, size_t iterations=1) {
            std::string hash;
            
            hash.resize(128 / 8);
            MD5(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
            
            for (size_t c = 1; c < iterations; ++c)
              MD5(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
            
            return hash;
        }

        static std::string sha1(const std::string &input, size_t iterations=1) {
            std::string hash;
            
            hash.resize(160 / 8);
            SHA1(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
            
            for (size_t c = 1; c < iterations; ++c)
              SHA1(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
            
            return hash;
        }

        static std::string sha256(const std::string &input, size_t iterations=1) {
            std::string hash;
            
            hash.resize(256 / 8);
            SHA256(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
            
            for (size_t c = 1; c < iterations; ++c)
              SHA256(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
            
            return hash;
        }

        static std::string sha512(const std::string &input, size_t iterations=1) {
            std::string hash;
            
            hash.resize(512 / 8);
            SHA512(reinterpret_cast<const unsigned char*>(&input[0]), input.size(), reinterpret_cast<unsigned char*>(&hash[0]));
            
            for (size_t c = 1; c < iterations; ++c)
              SHA512(reinterpret_cast<const unsigned char*>(&hash[0]), hash.size(), reinterpret_cast<unsigned char*>(&hash[0]));
            
            return hash;
        }
    };
}
#endif	/* CRYPTO_HPP */