diff --git a/CMakeLists.txt b/CMakeLists.txt index 11f896e..47593ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,8 @@ set( fc_sources src/log/console_appender.cpp src/log/file_appender.cpp src/log/logger_config.cpp + src/crypto/openssl.cpp + src/crypto/aes.cpp src/crypto/crc.cpp src/crypto/city.cpp src/crypto/base32.cpp @@ -116,6 +118,7 @@ set( fc_sources src/network/ip.cpp src/network/resolve.cpp src/network/url.cpp + src/compress/smaz.cpp vendor/cyoencode-1.0.2/src/CyoDecode.c vendor/cyoencode-1.0.2/src/CyoEncode.c ) @@ -126,4 +129,8 @@ set( sources setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC ) +set( BOOST_LIBRARIES ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_CHRONO_LIBRARY} ${ALL_OPENSSL_LIBRARIES} ${Boost_COROUTINE_LIBRARY} ${Boost_CONTEXT_LIBRARY} ) + +#add_executable( test_compress tests/compress.cpp ) +#target_link_libraries( test_compress fc ${BOOST_LIBRARIES} ) diff --git a/include/fc/crypto/aes.hpp b/include/fc/crypto/aes.hpp new file mode 100644 index 0000000..a840be7 --- /dev/null +++ b/include/fc/crypto/aes.hpp @@ -0,0 +1,9 @@ +#pragma once +#include + +namespace fc { + +std::vector aes_encrypt( const fc::sha512& key, const std::vector& plain_text ); +std::vector aes_decrypt( const fc::sha512& key, const std::vector& cipher_text ); + +} diff --git a/include/fc/crypto/openssl.hpp b/include/fc/crypto/openssl.hpp new file mode 100644 index 0000000..bb42788 --- /dev/null +++ b/include/fc/crypto/openssl.hpp @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @file openssl.hpp + * Provides common utility calls for wrapping openssl c api. + */ +namespace fc +{ + + template + struct ssl_wrapper + { + ssl_wrapper(ssl_type* obj):obj(obj) {} + + operator ssl_type*() + { + return obj; + } + ssl_type* operator->() { return obj; } + + ssl_type* obj; + }; + + #define SSL_TYPE(name, ssl_type, free_func) \ + struct name : public ssl_wrapper \ + { \ + name(ssl_type* obj) \ + : ssl_wrapper(obj) {} \ + ~name() \ + { \ + free_func(obj); \ + } \ + }; + + SSL_TYPE(ec_group, EC_GROUP, EC_GROUP_free) + SSL_TYPE(ec_point, EC_POINT, EC_POINT_free) + SSL_TYPE(ecdsa_sig, ECDSA_SIG, ECDSA_SIG_free) + SSL_TYPE(bn_ctx, BN_CTX, BN_CTX_free) + SSL_TYPE(evp_cipher_ctx, EVP_CIPHER_CTX, EVP_CIPHER_CTX_free ) + + /** allocates a bignum by default.. */ + struct ssl_bignum : public ssl_wrapper + { + ssl_bignum() : ssl_wrapper(BN_new()) {} + ~ssl_bignum() { BN_free(obj); } + }; + + int init_openssl(); + +} // namespace fc diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp new file mode 100644 index 0000000..a771035 --- /dev/null +++ b/src/crypto/aes.cpp @@ -0,0 +1,130 @@ +#include +#include +#include + +namespace fc { + +static int init = init_openssl(); + +/** example method from wiki.opensslfoundation.com */ +int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, + unsigned char *iv, unsigned char *ciphertext) +{ + evp_cipher_ctx ctx( EVP_CIPHER_CTX_new() ); + + int len = 0; + int ciphertext_len = 0; + + /* Create and initialise the context */ + if(!ctx) + { + FC_THROW_EXCEPTION( exception, "error allocating evp cipher context", + ("s", ERR_error_string( ERR_get_error(), nullptr) ) ); + } + + /* Initialise the encryption operation. IMPORTANT - ensure you use a key + * * and IV size appropriate for your cipher + * * In this example we are using 256 bit AES (i.e. a 256 bit key). The + * * IV size for *most* modes is the same as the block size. For AES this + * * is 128 bits */ + if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) + { + FC_THROW_EXCEPTION( exception, "error durring aes 256 cbc encryption init", + ("s", ERR_error_string( ERR_get_error(), nullptr) ) ); + } + + /* Provide the message to be encrypted, and obtain the encrypted output. + * * EVP_EncryptUpdate can be called multiple times if necessary + * */ + if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) + { + FC_THROW_EXCEPTION( exception, "error durring aes 256 cbc encryption update", + ("s", ERR_error_string( ERR_get_error(), nullptr) ) ); + } + ciphertext_len = len; + + /* Finalise the encryption. Further ciphertext bytes may be written at + * * this stage. + * */ + if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) + { + FC_THROW_EXCEPTION( exception, "error durring aes 256 cbc encryption final", + ("s", ERR_error_string( ERR_get_error(), nullptr) ) ); + } + ciphertext_len += len; + + return ciphertext_len; +} + +int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, + unsigned char *iv, unsigned char *plaintext) +{ + evp_cipher_ctx ctx( EVP_CIPHER_CTX_new() ); + int len = 0; + int plaintext_len = 0; + + /* Create and initialise the context */ + if(!ctx) + { + FC_THROW_EXCEPTION( exception, "error allocating evp cipher context", + ("s", ERR_error_string( ERR_get_error(), nullptr) ) ); + } + + /* Initialise the decryption operation. IMPORTANT - ensure you use a key + * * and IV size appropriate for your cipher + * * In this example we are using 256 bit AES (i.e. a 256 bit key). The + * * IV size for *most* modes is the same as the block size. For AES this + * * is 128 bits */ + if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) + { + FC_THROW_EXCEPTION( exception, "error durring aes 256 cbc decrypt init", + ("s", ERR_error_string( ERR_get_error(), nullptr) ) ); + } + + /* Provide the message to be decrypted, and obtain the plaintext output. + * * EVP_DecryptUpdate can be called multiple times if necessary + * */ + if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) + { + FC_THROW_EXCEPTION( exception, "error durring aes 256 cbc decrypt update", + ("s", ERR_error_string( ERR_get_error(), nullptr) ) ); + } + + plaintext_len = len; + + /* Finalise the decryption. Further plaintext bytes may be written at + * * this stage. + * */ + if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) + { + FC_THROW_EXCEPTION( exception, "error durring aes 256 cbc decrypt final", + ("s", ERR_error_string( ERR_get_error(), nullptr) ) ); + } + plaintext_len += len; + + return plaintext_len; +} + + + +std::vector aes_encrypt( const fc::sha512& key, const std::vector& plain_text ) +{ + std::vector cipher_text(plain_text.size()+16); + auto cipher_len = aes_encrypt( (unsigned char*)plain_text.data(), plain_text.size(), + (unsigned char*)&key, ((unsigned char*)&key)+32, + (unsigned char*)cipher_text.data() ); + cipher_text.resize(cipher_len); + return cipher_text; + +} +std::vector aes_decrypt( const fc::sha512& key, const std::vector& cipher_text ) +{ + std::vector plain_text( cipher_text.size() ); + auto plain_len = aes_decrypt( (unsigned char*)cipher_text.data(), cipher_text.size(), + (unsigned char*)&key, ((unsigned char*)&key)+32, + (unsigned char*)plain_text.data() ); + plain_text.resize(plain_len); + return plain_text; +} + +} // namespace fc diff --git a/src/crypto/elliptic.cpp b/src/crypto/elliptic.cpp index 5025893..704f5cb 100644 --- a/src/crypto/elliptic.cpp +++ b/src/crypto/elliptic.cpp @@ -2,61 +2,11 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include #include namespace fc { namespace ecc { - -template -struct ssl_wrapper -{ - ssl_wrapper(ssl_type* obj) - : obj(obj) {} - virtual ~ssl_wrapper() - { - } - operator ssl_type*() - { - return obj; - } - ssl_type* operator->() { return obj; } - - ssl_type* obj; -}; - -struct ssl_bignum - : public ssl_wrapper -{ - ssl_bignum() - : ssl_wrapper(BN_new()) {} - ~ssl_bignum() - { - BN_free(obj); - } -}; - - #define SSL_TYPE(name, ssl_type, free_func) \ - struct name \ - : public ssl_wrapper \ - { \ - name(ssl_type* obj) \ - : ssl_wrapper(obj) {} \ - ~name() \ - { \ - free_func(obj); \ - } \ - }; - - SSL_TYPE(ec_group, EC_GROUP, EC_GROUP_free) - SSL_TYPE(ec_point, EC_POINT, EC_POINT_free) - SSL_TYPE(ecdsa_sig, ECDSA_SIG, ECDSA_SIG_free) - SSL_TYPE(bn_ctx, BN_CTX, BN_CTX_free) + static int init = init_openssl(); namespace detail { @@ -414,8 +364,6 @@ struct ssl_bignum return 1 == ECDSA_verify( 0, (unsigned char*)&digest, sizeof(digest), (unsigned char*)&sig, sizeof(sig), my->_key ); } - static int load_ssl_error = [=](){ ERR_load_crypto_strings(); return 1; }(); - public_key_data public_key::serialize()const { public_key_data dat; diff --git a/src/crypto/openssl.cpp b/src/crypto/openssl.cpp new file mode 100644 index 0000000..ae43cfb --- /dev/null +++ b/src/crypto/openssl.cpp @@ -0,0 +1,24 @@ +#include +namespace fc +{ + struct openssl_scope + { + openssl_scope() + { + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); + OPENSSL_config(NULL); + } + ~openssl_scope() + { + EVP_cleanup(); + ERR_free_strings(); + } + }; + + int init_openssl() + { + static openssl_scope ossl; + return 0; + } +}