From 7ba6afb53a2f6ac4bfb68c9bcc4b3a50e69d6254 Mon Sep 17 00:00:00 2001 From: Steven de Ridder Date: Mon, 24 Jan 2022 15:35:10 +0100 Subject: [PATCH] Initial commit. dependencies not resolved yet. --- .gitignore | 2 ++ CMakeLists.txt | 25 +++++++++++++++++++++++++ README.md | 0 src/CMakeLists.txt | 33 +++++++++++++++++++++++++++++++++ src/crypter.cpp | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/crypter.h | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/scopeguard.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/scopeguard.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ 9 files changed, 402 insertions(+), 0 deletions(-) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 src/CMakeLists.txt create mode 100644 src/crypter.cpp create mode 100644 src/crypter.h create mode 100644 src/scopeguard.cpp create mode 100644 src/scopeguard.h create mode 100644 tests/CMakeLists.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ff047c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +CMakeLists.txt.user diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..642ed76 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.0) + +# Check to see where cmake is located. +if( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake ) + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +elseif( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../cmake ) + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +else() + return() +endif() + +# Check to see if there is versioning information available +if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/osdev_versioning/cmake) + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/osdev_versioning/cmake) + include(osdevversion) +endif() + +include(projectheader) +project_header(osdev_crypter) + +add_subdirectory(src) +add_subdirectory(tests) + +# include(packaging) +# package_component() diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/README.md diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..641a2d0 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.0) +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../external/hsoa_create_version_include/cmake) +include(projectheader) +project_header(crypter) + +find_package( Qt5Core REQUIRED ) + +include_directories( SYSTEM + ${Qt5Core_INCLUDE_DIRS} +) + +include(compiler) + +set(SRC_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/crypter.h + ${CMAKE_CURRENT_SOURCE_DIR}/crypter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/scopeguard.h + ${CMAKE_CURRENT_SOURCE_DIR}/scopeguard.cpp +) + +link_directories( + ${CMAKE_BINARY_DIR}/lib +) + +include(library) +add_libraries( + ${Qt5Core_LIBRARIES} + crypto + logutils +) + +include(installation) +install_component() diff --git a/src/crypter.cpp b/src/crypter.cpp new file mode 100644 index 0000000..fba2164 --- /dev/null +++ b/src/crypter.cpp @@ -0,0 +1,137 @@ +/* **************************************************************************** + * Copyright 2019 Open Systems Development BV * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the "Software"), * + * to deal in the Software without restriction, including without limitation * + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * + * and/or sell copies of the Software, and to permit persons to whom the * + * Software is furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included in * + * all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * + * DEALINGS IN THE SOFTWARE. * + * ***************************************************************************/ + +#include "crypter.h" + +// std +#include +#include +#include +#include +#include + +// openssl +#include + +// osdev::components +#include "log.h" +#include "scopeguard.h" + +using namespace osdev::components; + +namespace { + +const EVP_MD* getAlgo( Crypter::AlgorithmEnum algo ) +{ + switch ( algo ) + { + case Crypter::AlgorithmEnum::MD0: + return EVP_md_null(); + case Crypter::AlgorithmEnum::MD2: + // return EVP_md2(); + case Crypter::AlgorithmEnum::MD5: + return EVP_md5(); + case Crypter::AlgorithmEnum::MDC2: + // deprecated. + // md = EVP_mdc2(); + return EVP_md_null(); + case Crypter::AlgorithmEnum::SHA1: + return EVP_sha1(); + case Crypter::AlgorithmEnum::SHA224: + return EVP_sha224(); + case Crypter::AlgorithmEnum::SHA256: + return EVP_sha256(); + case Crypter::AlgorithmEnum::SHA384: + return EVP_sha384(); + case Crypter::AlgorithmEnum::SHA512: + return EVP_sha512(); + case Crypter::AlgorithmEnum::RIPEMD160: + return EVP_ripemd160(); + } + + throw std::invalid_argument("Crypto algorithm not found."); +} + +} // anonymous + +Crypter::Crypter() +{ +} + +std::string Crypter::encrypt( const std::string& message, Crypter::AlgorithmEnum algo ) +{ + // Create the environment + auto md = getAlgo(algo); + +#if OPENSSL_VERSION_NUMBER >= 0x1010008fL + auto mdContext = std::unique_ptr( + EVP_MD_CTX_create(), + [](EVP_MD_CTX* ptr){EVP_MD_CTX_free(ptr);}); + + // This will call EVP_cleanup if the guard goes out of scope. + ScopeGuard oGuard( &EVP_PBE_cleanup ); +#else + auto mdContext = std::unique_ptr( + EVP_MD_CTX_create(), + [](EVP_MD_CTX* ptr){EVP_MD_CTX_destroy(ptr);}); + + // This will call EVP_cleanup if the guard goes out of scope. + ScopeGuard oGuard( &EVP_cleanup ); +#endif + + (void)oGuard; // Satisfy the compiler for unused variables. + + auto errorCode = EVP_DigestInit_ex( mdContext.get(), md, NULL ); + if( 1 != errorCode ) + { + LogError( "[Crypter::encrypt]", QString( "No encryption digest environment created." ) ); + throw std::system_error( errorCode, std::system_category(), "No encryption digest environment created." ); + } + + // Update the environment with the message + errorCode = EVP_DigestUpdate( mdContext.get(), message.c_str(), message.length() ); + if( 1 != errorCode ) + { + LogError( "[Crypter::encrypt]", QString("Digest failed.") ); + throw std::system_error( errorCode, std::system_category(), "Digest failed.." ); + } + + // End the Digest so we can read the crypted message. + unsigned int mdLen; + unsigned char mdValue[EVP_MAX_MD_SIZE]; + errorCode = EVP_DigestFinal_ex( mdContext.get(), mdValue, &mdLen ); + if( 1 != errorCode ) + { + LogError( "[Crypter::encrypt]", QString("There was an error closing the digest environment.") ); + throw std::system_error( errorCode, std::system_category(), "There was an error closing the digest environment." ); + } + + // If we got here, all went well. We retrieve the crypted message + // through a stringstream : convert to hex, padding and width and return the string. + std::stringstream ss; + for( unsigned int nIndex = 0; nIndex < mdLen; nIndex++ ) + { + ss << std::hex << std::setw( 2 ) << std::setfill( '0' ) << static_cast( mdValue[nIndex] ); + } + + return ss.str(); +} diff --git a/src/crypter.h b/src/crypter.h new file mode 100644 index 0000000..f3f5d4b --- /dev/null +++ b/src/crypter.h @@ -0,0 +1,72 @@ +/* **************************************************************************** + * Copyright 2019 Open Systems Development BV * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the "Software"), * + * to deal in the Software without restriction, including without limitation * + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * + * and/or sell copies of the Software, and to permit persons to whom the * + * Software is furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included in * + * all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * + * DEALINGS IN THE SOFTWARE. * + * ***************************************************************************/ + +#ifndef OSDEV_COMPONENTS_CRYPTER_H +#define OSDEV_COMPONENTS_CRYPTER_H + +// std +#include + +namespace osdev { +namespace components { + +/** + * @brief Provides encryption/hashing functionality. + */ +class Crypter +{ +public: + /** + * @brief Defines the encryption/hashing algorithms. + */ + enum class AlgorithmEnum + { + MD0, ///< Empty initializer. + MD2, + MD5, + MDC2, + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, + RIPEMD160 + }; + + /** + * @brief Constructs a default instance of Crypter. + */ + Crypter(); + + /** + * @brief Encrypts the specified message using the specified algorithm. + * @param message The message to encrypt. + * @param algo The encryption algorithm to use. The default value is SHA256. + * @return The encrypted string. + */ + static std::string encrypt( const std::string& message, Crypter::AlgorithmEnum algo = Crypter::AlgorithmEnum::SHA256 ); +}; + +} /* End namespace components */ +} /* End namespace osdev */ + +#endif /* OSDEV_COMPONENTS_CRYPTER_H */ diff --git a/src/scopeguard.cpp b/src/scopeguard.cpp new file mode 100644 index 0000000..82455a4 --- /dev/null +++ b/src/scopeguard.cpp @@ -0,0 +1,42 @@ +/* **************************************************************************** + * Copyright 2019 Open Systems Development BV * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the "Software"), * + * to deal in the Software without restriction, including without limitation * + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * + * and/or sell copies of the Software, and to permit persons to whom the * + * Software is furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included in * + * all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * + * DEALINGS IN THE SOFTWARE. * + * ***************************************************************************/ + +#include "scopeguard.h" + +using namespace osdev::components; + +ScopeGuard::ScopeGuard( const CleanUpFunction& cleanupFunc ) + : m_cleanupFunc( cleanupFunc ) +{ +} + +ScopeGuard::~ScopeGuard() noexcept +{ + try + { + if( m_cleanupFunc ) + { + m_cleanupFunc(); + } + } + catch (...) {} +} diff --git a/src/scopeguard.h b/src/scopeguard.h new file mode 100644 index 0000000..29366eb --- /dev/null +++ b/src/scopeguard.h @@ -0,0 +1,61 @@ +/* **************************************************************************** + * Copyright 2019 Open Systems Development BV * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the "Software"), * + * to deal in the Software without restriction, including without limitation * + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * + * and/or sell copies of the Software, and to permit persons to whom the * + * Software is furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included in * + * all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * + * DEALINGS IN THE SOFTWARE. * + * ***************************************************************************/ + +#ifndef OSDEV_COMPONENTS_SCOPEGUARD_H +#define OSDEV_COMPONENTS_SCOPEGUARD_H + +#include + +namespace osdev { +namespace components { + +using CleanUpFunction = std::function; + +/** + * @brief Ensures that a cleanup function is called at the end of the current scope. + */ +class ScopeGuard +{ +public: + + /** + * @brief Constructs a RAII instance that will call cleanupFunc in it's destructor. + * @param cleanupFunc The cleanup function to call at the end of the current scope. + * This cleanup function must not throw exceptions. If it does, the behaviour + * is undefined. + */ + ScopeGuard( const CleanUpFunction& cleanupFunc ); + + // not copyable + ScopeGuard( const ScopeGuard& ) = delete; + ScopeGuard& operator=( const ScopeGuard& ) = delete; + + ~ScopeGuard() noexcept; + +private: + CleanUpFunction m_cleanupFunc; +}; + +} /* End namespace components */ +} /* End namespace osdev */ + +#endif /* OSDEV_COMPONENTS_SCOPEGUARD_H */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..3635320 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.0) +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) + +include(projectheader) +project_header(test_logutils) + +include_directories( SYSTEM + ${CMAKE_CURRENT_SOURCE_DIR}/../../src +) + +include(compiler) +set(SRC_LIST +) + +# add_executable( ${PROJECT_NAME} +# ${SRC_LIST} +# ) + +# target_link_libraries( +# ${PROJECT_NAME} +# ) + +# set_target_properties( ${PROJECT_NAME} PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +# LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib +# ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/archive +# ) + +# include(installation) +# install_application() -- libgit2 0.21.4