Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
aes.cpp
Go to the documentation of this file.
1#include <fc/crypto/aes.hpp>
4#include <fc/fwd_impl.hpp>
5
6//#include <fc/io/fstream.hpp>
7#include <fc/io/raw.hpp>
8
9#include <fc/log/logger.hpp>
10
11#include <openssl/opensslconf.h>
12#ifndef OPENSSL_THREADS
13# error "OpenSSL must be configured to support threads"
14#endif
15#include <openssl/crypto.h>
16
17#if defined(_WIN32)
18# include <windows.h>
19#endif
20
21#include <thread>
22#include <mutex>
23#include <fstream>
24#include <functional>
25
26namespace fc {
27
29{
30 evp_cipher_ctx ctx;
31};
32
33
34void aes_encoder::init( const fc::sha256& key, const fc::uint128& init_value )
35{
36 my->ctx.obj = EVP_CIPHER_CTX_new();
37 /* Create and initialise the context */
38 if(!my->ctx)
39 {
40 FC_THROW_EXCEPTION( aes_exception, "error allocating evp cipher context",
41 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
42 }
43
44 /* Initialise the encryption operation. IMPORTANT - ensure you use a key
45 * and IV size appropriate for your cipher
46 * In this example we are using 256 bit AES (i.e. a 256 bit key). The
47 * IV size for *most* modes is the same as the block size. For AES this
48 * is 128 bits */
49 if(1 != EVP_EncryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (unsigned char*)&init_value))
50 {
51 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init",
52 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
53 }
54 EVP_CIPHER_CTX_set_padding( my->ctx, 0 );
55}
56
57uint32_t aes_encoder::encode( const char* plaintxt, uint32_t plaintext_len, char* ciphertxt )
58{
59 int ciphertext_len = 0;
60 /* Provide the message to be encrypted, and obtain the encrypted output.
61 * * EVP_EncryptUpdate can be called multiple times if necessary
62 * */
63 if(1 != EVP_EncryptUpdate(my->ctx, (unsigned char*)ciphertxt, &ciphertext_len, (const unsigned char*)plaintxt, plaintext_len))
64 {
65 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption update",
66 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
67 }
68 FC_ASSERT( ciphertext_len == static_cast<int>(plaintext_len), "", ("ciphertext_len",ciphertext_len)("plaintext_len",plaintext_len) );
69 return ciphertext_len;
70}
71#if 0
72uint32_t aes_encoder::final_encode( char* ciphertxt )
73{
74 int ciphertext_len = 0;
75 /* Finalise the encryption. Further ciphertext bytes may be written at
76 * * this stage.
77 * */
78 if(1 != EVP_EncryptFinal_ex(my->ctx, (unsigned char*)ciphertxt, &ciphertext_len))
79 {
80 FC_THROW_EXCEPTION( exception, "error during aes 256 cbc encryption final",
81 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
82 }
83 return ciphertext_len;
84}
85#endif
86
87
89{
90 evp_cipher_ctx ctx;
91};
92
93void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value )
94{
95 my->ctx.obj = EVP_CIPHER_CTX_new();
96 /* Create and initialise the context */
97 if(!my->ctx)
98 {
99 FC_THROW_EXCEPTION( aes_exception, "error allocating evp cipher context",
100 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
101 }
102
103 /* Initialise the encryption operation. IMPORTANT - ensure you use a key
104 * and IV size appropriate for your cipher
105 * In this example we are using 256 bit AES (i.e. a 256 bit key). The
106 * IV size for *most* modes is the same as the block size. For AES this
107 * is 128 bits */
108 if(1 != EVP_DecryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (unsigned char*)&init_value))
109 {
110 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init",
111 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
112 }
113 EVP_CIPHER_CTX_set_padding( my->ctx, 0 );
114}
115
116uint32_t aes_decoder::decode( const char* ciphertxt, uint32_t ciphertxt_len, char* plaintext )
117{
118 int plaintext_len = 0;
119 /* Provide the message to be decrypted, and obtain the decrypted output.
120 * * EVP_DecryptUpdate can be called multiple times if necessary
121 * */
122 if (1 != EVP_DecryptUpdate(my->ctx, (unsigned char*)plaintext, &plaintext_len, (const unsigned char*)ciphertxt, ciphertxt_len))
123 {
124 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc decryption update",
125 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
126 }
127 FC_ASSERT( ciphertxt_len == static_cast<unsigned>(plaintext_len), "", ("ciphertxt_len",ciphertxt_len)("plaintext_len",plaintext_len) );
128 return plaintext_len;
129}
130#if 0
131uint32_t aes_decoder::final_decode( char* plaintext )
132{
133 return 0;
134 int ciphertext_len = 0;
135 /* Finalise the encryption. Further ciphertext bytes may be written at
136 * * this stage.
137 * */
138 if(1 != EVP_DecryptFinal_ex(my->ctx, (unsigned char*)plaintext, &ciphertext_len))
139 {
140 FC_THROW_EXCEPTION( exception, "error during aes 256 cbc encryption final",
141 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
142 }
143 return ciphertext_len;
144}
145#endif
146
147
148
149
150
151
152
153
154
155
156
157
159unsigned aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
160 unsigned char *iv, unsigned char *ciphertext)
161{
162 evp_cipher_ctx ctx( EVP_CIPHER_CTX_new() );
163
164 int len = 0;
165 unsigned ciphertext_len = 0;
166
167 /* Create and initialise the context */
168 if(!ctx)
169 {
170 FC_THROW_EXCEPTION( aes_exception, "error allocating evp cipher context",
171 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
172 }
173
174 /* Initialise the encryption operation. IMPORTANT - ensure you use a key
175 * and IV size appropriate for your cipher
176 * In this example we are using 256 bit AES (i.e. a 256 bit key). The
177 * IV size for *most* modes is the same as the block size. For AES this
178 * is 128 bits */
179 if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
180 {
181 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init",
182 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
183 }
184
185 /* Provide the message to be encrypted, and obtain the encrypted output.
186 * * EVP_EncryptUpdate can be called multiple times if necessary
187 * */
188 if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
189 {
190 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption update",
191 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
192 }
193 ciphertext_len = len;
194
195 /* Finalise the encryption. Further ciphertext bytes may be written at
196 * * this stage.
197 * */
198 if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
199 {
200 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption final",
201 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
202 }
203 ciphertext_len += len;
204
205 return ciphertext_len;
206}
207
208unsigned aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
209 unsigned char *iv, unsigned char *plaintext)
210{
211 evp_cipher_ctx ctx( EVP_CIPHER_CTX_new() );
212 int len = 0;
213 unsigned plaintext_len = 0;
214
215 /* Create and initialise the context */
216 if(!ctx)
217 {
218 FC_THROW_EXCEPTION( aes_exception, "error allocating evp cipher context",
219 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
220 }
221
222 /* Initialise the decryption operation. IMPORTANT - ensure you use a key
223 * * and IV size appropriate for your cipher
224 * * In this example we are using 256 bit AES (i.e. a 256 bit key). The
225 * * IV size for *most* modes is the same as the block size. For AES this
226 * * is 128 bits */
227 if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
228 {
229 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc decrypt init",
230 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
231 }
232
233 /* Provide the message to be decrypted, and obtain the plaintext output.
234 * * EVP_DecryptUpdate can be called multiple times if necessary
235 * */
236 if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
237 {
238 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc decrypt update",
239 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
240 }
241
242 plaintext_len = len;
243
244 /* Finalise the decryption. Further plaintext bytes may be written at
245 * * this stage.
246 * */
247 if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
248 {
249 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc decrypt final",
250 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
251 }
252 plaintext_len += len;
253
254 return plaintext_len;
255}
256
257unsigned aes_cfb_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
258 unsigned char *iv, unsigned char *plaintext)
259{
260 evp_cipher_ctx ctx( EVP_CIPHER_CTX_new() );
261 int len = 0;
262 unsigned plaintext_len = 0;
263
264 /* Create and initialise the context */
265 if(!ctx)
266 {
267 FC_THROW_EXCEPTION( aes_exception, "error allocating evp cipher context",
268 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
269 }
270
271 /* Initialise the decryption operation. IMPORTANT - ensure you use a key
272 * * and IV size appropriate for your cipher
273 * * In this example we are using 256 bit AES (i.e. a 256 bit key). The
274 * * IV size for *most* modes is the same as the block size. For AES this
275 * * is 128 bits */
276 if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cfb128(), NULL, key, iv))
277 {
278 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc decrypt init",
279 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
280 }
281
282 /* Provide the message to be decrypted, and obtain the plaintext output.
283 * * EVP_DecryptUpdate can be called multiple times if necessary
284 * */
285 if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
286 {
287 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc decrypt update",
288 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
289 }
290
291 plaintext_len = len;
292
293 /* Finalise the decryption. Further plaintext bytes may be written at
294 * * this stage.
295 * */
296 if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
297 {
298 FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc decrypt final",
299 ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
300 }
301 plaintext_len += len;
302
303 return plaintext_len;
304}
305
306std::vector<char> aes_encrypt( const fc::sha512& key, const std::vector<char>& plain_text )
307{
308 std::vector<char> cipher_text(plain_text.size()+16);
309 auto cipher_len = aes_encrypt( (unsigned char*)plain_text.data(), (int)plain_text.size(),
310 (unsigned char*)&key, ((unsigned char*)&key)+32,
311 (unsigned char*)cipher_text.data() );
312 FC_ASSERT( cipher_len <= cipher_text.size() );
313 cipher_text.resize(cipher_len);
314 return cipher_text;
315
316}
317std::vector<char> aes_decrypt( const fc::sha512& key, const std::vector<char>& cipher_text )
318{
319 std::vector<char> plain_text( cipher_text.size() );
320 auto plain_len = aes_decrypt( (unsigned char*)cipher_text.data(), (int)cipher_text.size(),
321 (unsigned char*)&key, ((unsigned char*)&key)+32,
322 (unsigned char*)plain_text.data() );
323 plain_text.resize(plain_len);
324 return plain_text;
325}
326
327
331void aes_save( const fc::path& file, const fc::sha512& key, std::vector<char> plain_text )
332{ try {
333 auto cipher = aes_encrypt( key, plain_text );
334 fc::sha512::encoder check_enc;
335 fc::raw::pack( check_enc, key );
336 fc::raw::pack( check_enc, cipher );
337 auto check = check_enc.result();
338
339 std::ofstream out(file.generic_string().c_str());
340 fc::raw::pack( out, check );
341 fc::raw::pack( out, cipher );
342} FC_RETHROW_EXCEPTIONS( warn, "", ("file",file) ) }
343
347std::vector<char> aes_load( const fc::path& file, const fc::sha512& key )
348{ try {
349 FC_ASSERT( fc::exists( file ) );
350
351 std::ifstream in( file.generic_string().c_str(), std::ifstream::binary );
352 fc::sha512 check;
353 std::vector<char> cipher;
354
355 fc::raw::unpack( in, check );
356 fc::raw::unpack( in, cipher );
357
358 fc::sha512::encoder check_enc;
359 fc::raw::pack( check_enc, key );
360 fc::raw::pack( check_enc, cipher );
361
362 FC_ASSERT( check_enc.result() == check );
363
364 return aes_decrypt( key, cipher );
365} FC_RETHROW_EXCEPTIONS( warn, "", ("file",file) ) }
366
367} // namespace fc
uint32_t decode(const char *ciphertxt, uint32_t len, char *plaintext)
Definition aes.cpp:116
void init(const fc::sha256 &key, const fc::uint128 &init_value)
Definition aes.cpp:93
void init(const fc::sha256 &key, const fc::uint128 &init_value)
Definition aes.cpp:34
uint32_t encode(const char *plaintxt, uint32_t len, char *ciphertxt)
Definition aes.cpp:57
Used to generate a useful error report when an exception is thrown.
Definition exception.hpp:58
wraps boost::filesystem::path to provide platform independent path manipulation.
an implementation of 128 bit unsigned integer
Definition uint128.hpp:22
Defines exception's used by fc.
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception's, std::exceptions, and ... and rethrows them after appending the provided log m...
void unpack(Stream &s, std::deque< T > &value)
Definition raw.hpp:540
void pack(Stream &s, const std::deque< T > &value)
Definition raw.hpp:531
namespace sysio::chain
Definition authority.cpp:3
unsigned aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext)
Definition aes.cpp:208
unsigned aes_cfb_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext)
Definition aes.cpp:257
bool exists(const path &p)
unsigned aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext)
Definition aes.cpp:159
void aes_save(const fc::path &file, const fc::sha512 &key, std::vector< char > plain_text)
Definition aes.cpp:331
std::vector< char > aes_load(const fc::path &file, const fc::sha512 &key)
Definition aes.cpp:347
unsigned int uint32_t
Definition stdint.h:126
evp_cipher_ctx ctx
Definition aes.cpp:90
evp_cipher_ctx ctx
Definition aes.cpp:30
size_t len