initial last commit

This commit is contained in:
Artem Nechitaylenko
2026-05-15 19:33:59 +05:00
commit 8d5f835a53
30 changed files with 2292 additions and 0 deletions

206
.gitignore vendored Normal file
View File

@@ -0,0 +1,206 @@
# ---> C
# Prerequisites
*.d
.idea/
.qtcreator
build/
.vscode/
.cache/
db-lib/.idea/
db-lib/cmake-build-debug
encrypt/.idea/
encrypt/cmake-build-debug/
#build dirs
build
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
builds/
# ---> C++
# Compiled Object files
*.slo
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
# ---> CMake
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
# ---> JetBrains
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# libre office
.~*.*
*.*#
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# *.iml
# *.ipr
# CMake
cmake-build-*/
*builds*/
# Mongo Explorer plugin
#.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
#.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
#.idea/httpRequests
# Android studio 3.1+ serialized cache file
#.idea/caches/build_file_checksums.ser
# ---> KDevelop4
*.kdev4
.kdev4/
# ---> Qt
# C++ objects and libs
# Qt-es
object_script.*.Release
object_script.*.Debug
*_plugin_import.cpp
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
moc_*.h
qrc_*.cpp
ui_*.h
*.qmlc
*.jsc
Makefile*
*build-*
*.qm
*.prl
# Qt unit tests
target_wrapper.*
# QtCreator
*.autosave
# QtCreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCreator CMake
CMakeLists.txt.user*
# QtCreator 4.8< compilation database
compile_commands.json
# QtCreator local machine specific files for imported projects
*creator.user*
*_qmlcache.qrc
# ---> VisualStudioCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/

85
CMakeLists.txt Normal file
View File

@@ -0,0 +1,85 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
set(crypt-lib octo-encryption-cpp)
if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
set(crypt-lib ${crypt-lib}d)
endif()
PROJECT(${crypt-lib})
# Add CMake options to path
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/)
INCLUDE(ConfigOptions)
# set libray dimention_name accessible to outer cmake files
set(ENCRYPT-LIB ${PROJECT_NAME} CACHE INTERNAL "")
#FIND_PACKAGE(OpenSSL REQUIRED CONFIG)
FIND_PACKAGE(OpenSSL REQUIRED)
# Library definition
ADD_LIBRARY(${PROJECT_NAME} STATIC
src/base64.cpp
src/secure-random.cpp
src/digests/ssl/ssl-digest.cpp
src/encryptors/encryptor.cpp
src/encryptors/sym-encrypt-layer-strategy.cpp
src/encryptors/ssl/ssl-cipher.cpp
src/encryptors/ssl/ssl-encryptor.cpp
)
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(OS "Windows")
set(lib_path C:/msys64/mingw64/lib)
file(GLOB libraries
${lib_path}/libssl.dll.a
${lib_path}/libcrypto.dll.a
)
endif()
# Alias
ADD_LIBRARY(core::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
# Properties
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES CXX_STANDARD 17 POSITION_INDEPENDENT_CODE ON)
TARGET_COMPILE_OPTIONS(${PROJECT_NAME}
PRIVATE
$<$<NOT:$<PLATFORM_ID:Windows>>:-Werror=return-type>
$<$<NOT:$<PLATFORM_ID:Windows>>:-Werror=switch>
)
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME}
PUBLIC
# Logger includes
${CMAKE_CURRENT_SOURCE_DIR}/include
)
TARGET_LINK_LIBRARIES(${PROJECT_NAME}
# System libraries
${libraries}
OpenSSL::SSL
OpenSSL::Crypto
)
# Installation of the logger
#INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
# DESTINATION include
#)
#INSTALL(TARGETS ${PROJECT_NAME}
# LIBRARY DESTINATION lib
# ARCHIVE DESTINATION lib
#)
# Unittests
#ADD_SUBDIRECTORY(unittests)
#IF(DISABLE_TESTS AND NOT WIN32)
# message(STATUS "-- TESTS ENABLED")
# ENABLE_TESTING()
# ADD_SUBDIRECTORY(unittests)
#ENDIF()

5
LICENSE Normal file
View File

@@ -0,0 +1,5 @@
Copyright (C) 2026 by artem artem-fbsd@home
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

93
README.md Normal file
View File

@@ -0,0 +1,93 @@
octo-encryption-cpp
==============
> cloned from https://github.com/ofiriluz/octo-encryption-cpp.git
[![Encryption Linux Build Pipeline](https://github.com/ofiriluz/octo-encryption-cpp/actions/workflows/linux.yml/badge.svg)](https://github.com/ofiriluz/octo-encryption-cpp/actions/workflows/linux.yml)
[![Encryption Windows Build Pipeline](https://github.com/ofiriluz/octo-encryption-cpp/actions/workflows/windows.yml/badge.svg)](https://github.com/ofiriluz/octo-encryption-cpp/actions/workflows/windows.yml)
[![Encryption Mac Build Pipeline](https://github.com/ofiriluz/octo-encryption-cpp/actions/workflows/mac.yml/badge.svg)](https://github.com/ofiriluz/octo-encryption-cpp/actions/workflows/mac.yml)
Encryption library in CPP, with base interfaces implemented with openssl
Interfaces implemented:
- Base64
- Secure random
- Digests
- Encryptors and secure strings
Usage
=====
Using the encryption library is based on openssl mostly, as such different interfaces can be used as follows:
Base64
------
```cpp
std::string text = "This is some text";
auto encoded = octo::encryption::Base64::base64_encode(text);
auto decoded = octo::encryption::Base64::base64_decode(encoded);
```
Secure random
-------------
Generate a secure random of size X, returns a vector of random bytes
```cpp
auto secure_random = octo::encryption::SecureRandom::generate_random(10);
```
Digests
-------
Supported Digests implemented:
- Sha224
- Sha256
- Sha384
- Sha512
Generating hashes for different digests
```cpp
auto digest = std::make_shared<octo::encryption::ssl::Sha512Digest>();
digest->update("SomeText");
digest->update("SomeOtherText");
auto hash = digest->finalize();
```
Encryptors and secure strings
-----------------------------
A base encryptor can encrypt and decrypt strings with materials (salts for the encryption)
Above that, we can define Secure / Encrypted strings, which are self destructed encrypted strings
We have 2 layers of secure strings:
- Layer 0 - SecureString, cleanup memory no encryption
- Layer 1 - SingleLayerEncryptedString, Single layer encryption
Above that, more can be implemented based on the interfaces defined
Example encryptor usage:
```cpp
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"Key1", "Key2", "Key3"});
auto e = octo::encryption::ssl::SSLEncryptor(std::make_shared<octo::encryption::ssl::SSLCipher>("AES256"));
auto encrypted = e.encrypt("Text", material);
std::string output;
auto decrypted = e.decrypt(encrypted, material, output)
```
Example SingleEncryptedString usage:
```cpp
auto encryptor = std::make_shared<octo::encryption::ssl::SSLEncryptor>(
std::make_shared<octo::encryption::ssl::SSLCipher>("AES256"));
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"Key1", "Key2", "Key3"});
octo::encryption::SingleEncryptedString encrypted_string(encryptor);
// Encryption
encrypted_string.set(input_plain_string, material);
// Decryption
auto output_plain_string = encrypted_string.get();
```

1
VERSION Normal file
View File

@@ -0,0 +1 @@
1.1.0

View File

@@ -0,0 +1 @@
OPTION(DISABLE_TESTS "Disable Tests Compilation" OFF)

View File

@@ -0,0 +1,32 @@
/**
* @file base64.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef BASE64_HPP_
#define BASE64_HPP_
#include <string>
#include <cstdint>
#include <cstddef>
namespace octo::encryption
{
class Base64
{
public:
Base64() = default;
virtual ~Base64() = default;
static std::string base64_encode(const std::string& plain_text);
static std::string base64_decode(const std::string& encoded_text);
};
} // namespace octo::encryption
#endif // BASE64_HPP_

View File

@@ -0,0 +1,69 @@
/**
* @file digest.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef DIGEST_HPP_
#define DIGEST_HPP_
#include <string>
#include <memory>
#include <vector>
#include <cstdint>
#include <cstddef>
namespace octo::encryption
{
class Digest
{
public:
Digest() = default;
Digest(const Digest&) = default;
Digest(Digest&&) = default;
virtual ~Digest() = default;
Digest& operator=(const Digest&) = default;
Digest& operator=(Digest&&) = default;
/**
* @brief Performs an update to the existing digest
*
* @param plain_text
*/
virtual void update(const std::string& plain_text) = 0;
virtual void update(const std::vector<char>& plain_text, std::size_t size) = 0;
virtual void update(const char* plain_text, std::size_t size) = 0;
virtual void update(const std::uint8_t* plain_text, std::size_t size) = 0;
/**
* @brief Resets the digest algorithm
*
*/
virtual void reset() = 0;
/**
* @brief Finalizes the digest and returns the output hash, should also reset the digest itself afterwards
*
* @return std::string
*/
virtual std::string finalize() = 0;
/**
* @brief Getter for the digest length
*
* @return std::size_t
*/
virtual std::size_t length() = 0;
/**
* @brief Clones the current digest
*
* @return
*/
virtual std::unique_ptr<Digest> clone() = 0;
};
typedef std::shared_ptr<Digest> DigestSharedPtr;
} // namespace octo::encryption
#endif // DIGEST_HPP_

View File

@@ -0,0 +1,96 @@
/**
* @file ssl-digest.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef SSL_DIGEST_HPP_
#define SSL_DIGEST_HPP_
#include "octo-encryption-cpp/digests/digest.hpp"
#include <memory>
#include <functional>
#include <openssl/evp.h>
namespace octo::encryption::ssl
{
class SSLDigest : public Digest
{
protected:
EVP_MD_CTX* digest_context_;
protected:
/**
* @brief Init the SSL digest based on the implemented class
*
*/
virtual void init_ssl_digest() = 0;
public:
SSLDigest();
~SSLDigest() override;
void update(const std::string& plain_text) override;
void update(const std::vector<char>& plain_text, std::size_t size) override;
void update(const char* plain_text, std::size_t size) override;
void update(const std::uint8_t* plain_text, std::size_t size) override;
void reset() override;
std::string finalize() override;
std::size_t length() override;
};
class Sha224Digest final : public SSLDigest
{
protected:
void init_ssl_digest() override;
public:
Sha224Digest() = default;
~Sha224Digest() override = default;
std::unique_ptr<Digest> clone() override;
};
class Sha256Digest final : public SSLDigest
{
protected:
void init_ssl_digest() override;
public:
Sha256Digest() = default;
~Sha256Digest() override = default;
std::unique_ptr<Digest> clone() override;
};
class Sha384Digest final : public SSLDigest
{
protected:
void init_ssl_digest() override;
public:
Sha384Digest() = default;
~Sha384Digest() override = default;
std::unique_ptr<Digest> clone() override;
};
class Sha512Digest final : public SSLDigest
{
protected:
void init_ssl_digest() override;
public:
Sha512Digest() = default;
~Sha512Digest() override = default;
std::unique_ptr<Digest> clone() override;
};
} // namespace octo::encryption::ssl
#endif // SSL_DIGEST_HPP_

View File

@@ -0,0 +1,201 @@
/**
* @file encrypted-string.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef SSL_ENCRYPTED_STRING_HPP_
#define SSL_ENCRYPTED_STRING_HPP_
#include <string>
#include <memory>
#include <vector>
#include <stdexcept>
#include "encryptor.hpp"
#include "sym-encrypt-layer-strategy.hpp"
#include "material.hpp"
namespace octo::encryption
{
template <class EncryptionStrategy>
class EncryptedString
{
static_assert(std::is_base_of<SymEncryptLayerStrategy, EncryptionStrategy>::value,
"strategy must inherit from SymEncryptLayerStrategy");
protected:
bool is_plain_exists_;
bool is_initialized_;
std::string plain_string_;
std::string ciphered_string_;
MaterialPtr material_;
EncryptorPtr encryptor_;
EncryptionStrategy encryption_strategy_;
public:
// Remove copy constructor and copy operators so it isn't copy-able
EncryptedString(const EncryptedString&) = delete;
virtual EncryptedString& operator=(const EncryptedString&) = delete;
virtual EncryptedString& operator=(EncryptedString&&) = delete;
EncryptedString(EncryptedString&& other) = delete;
public:
EncryptedString(const std::string& ciphered_string,
const MaterialPtr& material = MaterialPtr(),
const EncryptorPtr& encryptor = EncryptorPtr())
: is_plain_exists_(false),
is_initialized_(true),
plain_string_(""),
ciphered_string_(ciphered_string),
material_(material),
encryptor_(encryptor)
{
}
EncryptedString(const EncryptorPtr& encryptor = EncryptorPtr())
: is_plain_exists_(false),
is_initialized_(false),
plain_string_(""),
ciphered_string_(""),
encryptor_(encryptor)
{
}
virtual ~EncryptedString()
{
destruct();
Encryptor::secure_zeromem(ciphered_string_);
ciphered_string_ = "";
}
/**
* @brief Set a new EncryptedString by encrypting a plain_string using the material
*
* @param plain_string
* @param material
*/
void set(const std::string& plain_string, const MaterialPtr& material = MaterialPtr());
/**
* @brief Decrypt and return a plain string reference. Return value should not be copied!
*
* @return const std::string&
*/
const std::string& get();
/**
* @brief View only string reference of the current text, does not guarantee the text exists or was decrypted
*
* @return
*/
[[nodiscard]] std::string_view get() const;
/**
* @brief Swaps the current material with a new given material
*
* @param material
*/
void swap(const MaterialPtr& material);
inline const std::string& cipher()
{
return ciphered_string_;
}
inline MaterialPtr material()
{
return material_;
}
inline EncryptorPtr encryptor()
{
return encryptor_;
}
inline bool is_initialized()
{
return is_initialized_;
}
void destruct()
{
if (is_plain_exists_)
{
Encryptor::secure_zeromem(plain_string_);
plain_string_ = "";
is_plain_exists_ = false;
}
}
};
template <class EncryptionStrategy>
void EncryptedString<EncryptionStrategy>::set(const std::string& plain_string, const MaterialPtr& material)
{
material_ = material;
Encryptor::secure_zeromem(ciphered_string_);
encryption_strategy_.encrypt(plain_string, material, encryptor_, ciphered_string_);
is_initialized_ = true;
destruct();
}
template <class EncryptionStrategy>
const std::string& EncryptedString<EncryptionStrategy>::get()
{
// use the data member instead of decrypting again
if (is_plain_exists_)
{
return plain_string_;
}
// validate the cipher was set
if (!is_initialized_)
{
throw std::runtime_error("Error retrieving plain from non-initialized EncryptedString");
}
encryption_strategy_.decrypt(ciphered_string_, material_, encryptor_, plain_string_);
is_plain_exists_ = true;
return plain_string_;
}
template <class EncryptionStrategy>
std::string_view EncryptedString<EncryptionStrategy>::get() const
{
if (is_plain_exists_)
{
return plain_string_;
}
return ciphered_string_;
}
template <class EncryptionStrategy>
void EncryptedString<EncryptionStrategy>::swap(const MaterialPtr& material)
{
if (!is_plain_exists_)
{
encryption_strategy_.decrypt(ciphered_string_, material_, encryptor_, plain_string_);
is_plain_exists_ = true;
}
set(plain_string_, material);
}
// Define default SimpleEncryptedString with 1Layer encryption
typedef EncryptedString<SymEncryptOneLayerStrategy> SingleEncryptedString;
typedef std::shared_ptr<SingleEncryptedString> SingleEncryptedStringSharedPtr;
typedef std::unique_ptr<SingleEncryptedString> SingleEncryptedStringUniquePtr;
// Define default NotEncryptedString with NO encryption
typedef EncryptedString<SymEncryptZeroLayerStrategy> SecureString;
typedef std::shared_ptr<SecureString> SecureStringSharedPtr;
typedef std::unique_ptr<SecureString> SecureStringUniquePtr;
} // namespace octo::encryption
#endif // ENCRYPTED_STRING_HPP_

View File

@@ -0,0 +1,40 @@
/**
* @file encryptor.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef ENCRYPTOR_HPP_
#define ENCRYPTOR_HPP_
#include <string>
#include <memory>
#include <cstddef>
#include <cstdint>
#include "material.hpp"
namespace octo::encryption
{
class Encryptor
{
public:
Encryptor() = default;
virtual ~Encryptor() = default;
static void secure_zeromem(volatile char* message, std::size_t size);
static void secure_zeromem(std::string& message);
static void secure_zeromem(std::vector<std::uint8_t>& message);
virtual std::string encrypt(const std::string& message, const MaterialPtr& material) = 0;
virtual std::size_t decrypt(const std::string& message, const MaterialPtr& material, std::string& out_buffer) = 0;
};
typedef std::shared_ptr<Encryptor> EncryptorPtr;
typedef std::unique_ptr<Encryptor> EncryptorUniquePtr;
} // namespace octo::encryption
#endif // ENCRYPTOR_HPP_

View File

@@ -0,0 +1,36 @@
/**
* @file material.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef MATERIAL_HPP_
#define MATERIAL_HPP_
#include <string>
#include <memory>
#include <vector>
#include <cstddef>
#include <cstdint>
namespace octo::encryption
{
class Material
{
public:
Material() = default;
virtual ~Material() = default;
[[nodiscard]] virtual std::vector<std::string> generate() const = 0;
[[nodiscard]] virtual std::size_t size() const = 0;
};
typedef std::shared_ptr<Material> MaterialPtr;
typedef std::unique_ptr<Material> MaterialUniquePtr;
} // namespace octo::encryption
#endif // MATERIAL_HPP_

View File

@@ -0,0 +1,52 @@
/**
* @file simple-material.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef SIMPLE_MATERIAL_HPP_
#define SIMPLE_MATERIAL_HPP_
#include <string>
#include <memory>
#include <utility>
#include "../../include/octo-encryption-cpp/encryptors/material.hpp"
#include "../../include/octo-encryption-cpp/encryptors/encryptor.hpp"
namespace octo::encryption
{
class SimpleMaterial : public Material
{
private:
std::vector<std::string> materials_;
public:
explicit SimpleMaterial(std::vector<std::string> materials) : materials_(std::move(materials))
{
}
~SimpleMaterial() override
{
for (auto& m : materials_)
{
Encryptor::secure_zeromem(m);
}
materials_.clear();
}
[[nodiscard]] std::vector<std::string> generate() const override
{
return materials_;
}
[[nodiscard]] std::size_t size() const override
{
return materials_.size();
}
};
} // namespace octo::encryption
#endif // SIMPLE_MATERIAL_HPP_

View File

@@ -0,0 +1,45 @@
/**
* @file ssl-cipher.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef SSL_CIPHER_HPP_
#define SSL_CIPHER_HPP_
#include <string>
#include <memory>
#include <openssl/evp.h>
namespace octo::encryption::ssl
{
class SSLCipher
{
private:
const EVP_CIPHER* ssl_cipher_;
public:
explicit SSLCipher(const EVP_CIPHER* ssl_cipher);
explicit SSLCipher(const std::string& name);
explicit SSLCipher(int type);
~SSLCipher() = default;
[[nodiscard]] const EVP_CIPHER* cipher() const;
[[nodiscard]] int type() const;
[[nodiscard]] std::string name() const;
[[nodiscard]] std::size_t block_size() const;
[[nodiscard]] std::size_t key_length() const;
[[nodiscard]] std::size_t iv_length() const;
[[nodiscard]] unsigned long flags() const;
[[nodiscard]] unsigned long mode() const;
};
typedef std::shared_ptr<SSLCipher> SSLCipherSharedPtr;
} // namespace octo::encryption::ssl
#endif // SSL_MATERIAL_HPP_

View File

@@ -0,0 +1,38 @@
/**
* @file ssl-encryptor.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef SSL_ENCRYPTOR_HPP_
#define SSL_ENCRYPTOR_HPP_
#include "octo-encryption-cpp/encryptors/encryptor.hpp"
#include "octo-encryption-cpp/encryptors/material.hpp"
#include "ssl-cipher.hpp"
namespace octo::encryption::ssl
{
class SSLEncryptor : public Encryptor
{
private:
SSLCipherSharedPtr ssl_cipher_;
private:
std::unique_ptr<std::uint8_t[]> generate_key_material(const MaterialPtr& material);
public:
SSLEncryptor(const SSLCipherSharedPtr& cipher);
~SSLEncryptor() override = default;
std::string encrypt(const std::string& message, const MaterialPtr& material) override;
std::size_t decrypt(const std::string& message, const MaterialPtr& material, std::string& out_buffer) override;
};
} // namespace octo::encryption::ssl
#endif // SSL_ENCRYPTOR_HPP_

View File

@@ -0,0 +1,137 @@
/**
* @file sym-encrypt-layer-strategy.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include <string>
#include <cstddef>
#include <cstdint>
#include "material.hpp"
#include "encryptor.hpp"
#ifndef SYM_ENCRYPT_LAYER_STRATEGY_HPP_
#define SYM_ENCRYPT_LAYER_STRATEGY_HPP_
namespace octo::encryption
{
/**
* @brief Defines a layer-based symetrical encryption strategy
* Not suitable for binary data in non-character-format
*
*/
class SymEncryptLayerStrategy
{
public:
SymEncryptLayerStrategy() = default;
virtual ~SymEncryptLayerStrategy() = default;
/**
* @brief Encrypt the plain string using the material into ciphered_string
*
* @param plain_string
* @param material
* @param encryptor
* @param ciphered_string
*/
virtual void encrypt(const std::string& plain_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& ciphered_string) const = 0;
/**
* @brief Decrypt the ciphered_string using the material into plain_string
*
* @param ciphered_string
* @param material
* @param encryptor
* @param plain_string
* @return std::size_t
*/
virtual std::size_t decrypt(const std::string& ciphered_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& plain_string) const = 0;
};
/**
* @brief Defines a 0 layer symetrical encryption strategy (does not encrypt)
*
*/
class SymEncryptZeroLayerStrategy : public SymEncryptLayerStrategy
{
public:
SymEncryptZeroLayerStrategy() = default;
~SymEncryptZeroLayerStrategy() override = default;
/**
* @brief Encrypt the plain string using the material into ciphered_string
*
* @param plain_string
* @param material
* @param encryptor
* @param ciphered_string
*/
void encrypt(const std::string& plain_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& ciphered_string) const override;
/**
* @brief Decrypt the ciphered_string using the material into plain_string
*
* @param ciphered_string
* @param material
* @param encryptor
* @param plain_string
* @return std::size_t
*/
std::size_t decrypt(const std::string& ciphered_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& plain_string) const override;
};
/**
* @brief Defines a simple 1 layer encryption strategy
*
*/
class SymEncryptOneLayerStrategy : public SymEncryptLayerStrategy
{
public:
SymEncryptOneLayerStrategy() = default;
~SymEncryptOneLayerStrategy() override = default;
/**
* @brief Encrypt the plain string using the material into ciphered_string
*
* @param plain_string
* @param material
* @param encryptor
* @param ciphered_string
*/
void encrypt(const std::string& plain_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& ciphered_string) const override;
/**
* @brief Decrypt the ciphered_string using the material into plain_string
*
* @param ciphered_string
* @param material
* @param encryptor
* @param plain_string
* @return std::size_t
*/
std::size_t decrypt(const std::string& ciphered_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& plain_string) const override;
};
} // namespace octo::encryption
#endif // SYM_ENCRYPT_LAYER_STRATEGY_HPP_

View File

@@ -0,0 +1,31 @@
/**
* @file secure-random.hpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#ifndef SECURE_RANDOM_HPP_
#define SECURE_RANDOM_HPP_
#include <vector>
#include <cstdint>
#include <cstddef>
namespace octo::encryption
{
class SecureRandom
{
public:
SecureRandom() = default;
virtual ~SecureRandom() = default;
static std::vector<std::uint8_t> generate_random(std::size_t size);
};
} // namespace octo::encryption
#endif // SECURE_RANDOM_HPP_

85
src/base64.cpp Normal file
View File

@@ -0,0 +1,85 @@
/**
* @file base64.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include "octo-encryption-cpp/base64.hpp"
#include <stdexcept>
#include <cstring>
#include <openssl/evp.h>
#include <vector>
#include <memory>
namespace
{
struct bio_free_all
{
void operator()(BIO* p)
{
BIO_free_all(p);
}
};
} // namespace
namespace octo::encryption
{
std::string Base64::base64_encode(const std::string& plain_text)
{
// Assert input size
if (plain_text.empty())
{
return "";
}
// Create a BIO base64 with free all deleter
std::unique_ptr<BIO, bio_free_all> b64(BIO_new(BIO_f_base64()));
// Create the sink and push the data to it
BIO_set_flags(b64.get(), BIO_FLAGS_BASE64_NO_NL);
BIO* sink = BIO_new(BIO_s_mem());
BIO_push(b64.get(), sink);
// Encode and flush
BIO_write(b64.get(), plain_text.data(), plain_text.size());
BIO_flush(b64.get());
// Get encoded data
const char* encoded;
const long len = BIO_get_mem_data(sink, &encoded);
return std::string(encoded, len);
}
std::string Base64::base64_decode(const std::string& encoded_text)
{
// Assert input size
if (encoded_text.empty())
{
return "";
}
// Create a BIO base64 with free all deleter
std::unique_ptr<BIO, bio_free_all> b64(BIO_new(BIO_f_base64()));
// Create the sink and push the data to it
BIO_set_flags(b64.get(), BIO_FLAGS_BASE64_NO_NL);
BIO* source = BIO_new_mem_buf(encoded_text.c_str(), -1); // read-only source
BIO_push(b64.get(), source);
// Decode
const auto maxlen = encoded_text.size() / 4 * 3 + 1;
std::vector<std::uint8_t> decoded(maxlen);
const int len = BIO_read(b64.get(), decoded.data(), maxlen);
decoded.resize(len);
// Clear and return
std::string decoded_str(decoded.begin(), decoded.end());
std::memset(&decoded[0], 0, decoded.size());
return decoded_str;
}
} // namespace octo::encryption

View File

@@ -0,0 +1,216 @@
/**
* @file ssl-digest.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include "octo-encryption-cpp/digests/ssl/ssl-digest.hpp"
#include <sstream>
#include <iomanip>
#include <cstring>
namespace octo::encryption::ssl
{
SSLDigest::SSLDigest() : digest_context_(nullptr)
{
}
SSLDigest::~SSLDigest()
{
if (digest_context_)
{
EVP_MD_CTX_destroy(digest_context_);
digest_context_ = nullptr;
}
}
void SSLDigest::update(const std::string& plain_text)
{
update(plain_text.c_str(), plain_text.size());
}
void SSLDigest::update(const std::vector<char>& plain_text, std::size_t size)
{
update(plain_text.data(), size);
}
void SSLDigest::update(const char* plain_text, std::size_t size)
{
// Reset the context if not already created, for lazy load
if (!digest_context_)
{
reset();
}
// Perform the digest update and make sure it was successful
int rc = EVP_DigestUpdate(digest_context_, plain_text, size);
if (rc != 1)
{
throw std::runtime_error(std::string("Failed to update the SHA Digest [") + std::to_string(rc) +
"] (Diagnostics Info: 3)");
}
}
void SSLDigest::update(const std::uint8_t* plain_text, std::size_t size)
{
// Reset the context if not already created, for lazy load
if (!digest_context_)
{
reset();
}
// Perform the digest update and make sure it was successful
int rc = EVP_DigestUpdate(digest_context_, plain_text, size);
if (rc != 1)
{
throw std::runtime_error(std::string("Failed to update the SHA Digest [") + std::to_string(rc) +
"] (Diagnostics Info: 4)");
}
}
void SSLDigest::reset()
{
// Create the digest of SSL
if (digest_context_)
{
EVP_MD_CTX_destroy(digest_context_);
digest_context_ = nullptr;
}
digest_context_ = EVP_MD_CTX_create();
// Init the fitting SSL implementation
init_ssl_digest();
}
std::string SSLDigest::finalize()
{
// Reset the context if not already created, for lazy load
if (!digest_context_)
{
reset();
}
uint8_t buffer[EVP_MAX_MD_SIZE];
uint32_t digest_size = 0;
std::memset(buffer, 0x00, EVP_MAX_MD_SIZE);
// Perform the final digest and get the hash, make sure it was successful
int rc = EVP_DigestFinal_ex(digest_context_, buffer, &digest_size);
if (rc != 1)
{
throw std::runtime_error(std::string("Failed to finalize the SHA Digest [") + std::to_string(rc) + "]");
}
// Destroy the digest after we finalized it
EVP_MD_CTX_destroy(digest_context_);
digest_context_ = nullptr;
// Transform the bytes string to a normal string
std::stringstream ss;
ss << std::hex << std::setfill('0');
for (std::size_t i = 0; i < digest_size; i++)
{
ss << std::setw(2) << (int)buffer[i];
}
return ss.str();
}
std::size_t SSLDigest::length()
{
// Reset the context if not already created, for lazy load
if (!digest_context_)
{
reset();
}
return EVP_MD_CTX_size(digest_context_);
}
void Sha224Digest::init_ssl_digest()
{
// Init the SHA224 digest and check if was successful
int rc = EVP_DigestInit_ex(digest_context_, EVP_sha224(), nullptr);
if (rc != 1)
{
throw std::runtime_error(std::string("Failed to initialize the SHA224 Digest [") + std::to_string(rc) + "]");
}
}
std::unique_ptr<Digest> Sha224Digest::clone()
{
auto digest = std::make_unique<Sha224Digest>();
digest->digest_context_ = EVP_MD_CTX_create();
if (digest_context_)
{
EVP_MD_CTX_copy_ex(digest->digest_context_, digest_context_);
}
return std::move(digest);
}
void Sha256Digest::init_ssl_digest()
{
// Init the SHA256 digest and check if was successful
int rc = EVP_DigestInit_ex(digest_context_, EVP_sha256(), nullptr);
if (rc != 1)
{
throw std::runtime_error(std::string("Failed to initialize the SHA256 Digest [") + std::to_string(rc) + "]");
}
}
std::unique_ptr<Digest> Sha256Digest::clone()
{
auto digest = std::make_unique<Sha256Digest>();
digest->digest_context_ = EVP_MD_CTX_create();
if (digest_context_)
{
EVP_MD_CTX_copy_ex(digest->digest_context_, digest_context_);
}
return std::move(digest);
}
void Sha384Digest::init_ssl_digest()
{
// Init the SHA384 digest and check if was successful
int rc = EVP_DigestInit_ex(digest_context_, EVP_sha384(), nullptr);
if (rc != 1)
{
throw std::runtime_error(std::string("Failed to initialize the SHA384 Digest [") + std::to_string(rc) + "]");
}
}
std::unique_ptr<Digest> Sha384Digest::clone()
{
auto digest = std::make_unique<Sha384Digest>();
digest->digest_context_ = EVP_MD_CTX_create();
if (digest_context_)
{
EVP_MD_CTX_copy_ex(digest->digest_context_, digest_context_);
}
return std::move(digest);
}
void Sha512Digest::init_ssl_digest()
{
// Init the SHA512 digest and check if was successful
int rc = EVP_DigestInit_ex(digest_context_, EVP_sha512(), nullptr);
if (rc != 1)
{
throw std::runtime_error(std::string("Failed to initialize the SHA512 Digest [") + std::to_string(rc) + "]");
}
}
std::unique_ptr<Digest> Sha512Digest::clone()
{
auto digest = std::make_unique<Sha512Digest>();
digest->digest_context_ = EVP_MD_CTX_create();
if (digest_context_)
{
EVP_MD_CTX_copy_ex(digest->digest_context_, digest_context_);
}
return std::move(digest);
}
} // namespace octo::encryption::ssl

View File

@@ -0,0 +1,38 @@
/**
* @file encryptor.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include "octo-encryption-cpp/encryptors/encryptor.hpp"
namespace octo::encryption
{
void Encryptor::secure_zeromem(volatile char* message, std::size_t size)
{
if (message == nullptr)
{
return;
}
for (std::size_t i = 0; i < size; ++i)
{
*(((volatile char*)message) + i) ^= *(((volatile char*)message) + i);
}
}
void Encryptor::secure_zeromem(std::string& message)
{
secure_zeromem(reinterpret_cast<volatile char*>(&message[0]), message.size());
}
void Encryptor::secure_zeromem(std::vector<std::uint8_t>& message)
{
secure_zeromem(reinterpret_cast<volatile char*>(&message[0]), message.size());
}
} // namespace octo::encryption

View File

@@ -0,0 +1,78 @@
/**
* @file ssl-cipher.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include "octo-encryption-cpp/encryptors/ssl/ssl-cipher.hpp"
#include <stdexcept>
namespace octo::encryption::ssl
{
SSLCipher::SSLCipher(const EVP_CIPHER* ssl_cipher) : ssl_cipher_(ssl_cipher)
{
}
SSLCipher::SSLCipher(const std::string& name)
{
ssl_cipher_ = EVP_get_cipherbyname(name.c_str());
if (!ssl_cipher_)
{
throw std::runtime_error("Failed to find SSL Cipher by dimention_name");
}
}
SSLCipher::SSLCipher(int type)
{
ssl_cipher_ = EVP_get_cipherbynid(type);
if (!ssl_cipher_)
{
throw std::runtime_error("Failed to find SSL Cipher by type");
}
}
const EVP_CIPHER* SSLCipher::cipher() const
{
return ssl_cipher_;
}
int SSLCipher::type() const
{
return EVP_CIPHER_nid(ssl_cipher_);
}
std::string SSLCipher::name() const
{
return std::string(OBJ_nid2sn(type()));
}
std::size_t SSLCipher::block_size() const
{
return EVP_CIPHER_block_size(ssl_cipher_);
}
std::size_t SSLCipher::key_length() const
{
return EVP_CIPHER_key_length(ssl_cipher_);
}
std::size_t SSLCipher::iv_length() const
{
return EVP_CIPHER_iv_length(ssl_cipher_);
}
unsigned long SSLCipher::flags() const
{
return EVP_CIPHER_flags(ssl_cipher_);
}
unsigned long SSLCipher::mode() const
{
return EVP_CIPHER_mode(ssl_cipher_);
}
} // namespace octo::encryption::ssl

View File

@@ -0,0 +1,169 @@
/**
* @file ssl-encryptor.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include "octo-encryption-cpp/encryptors/ssl/ssl-encryptor.hpp"
#include "octo-encryption-cpp/digests/ssl/ssl-digest.hpp"
#include "octo-encryption-cpp/base64.hpp"
#include <openssl/evp.h>
#include <vector>
#include <sstream>
#include <cstring>
#include <iterator>
namespace octo::encryption::ssl
{
SSLEncryptor::SSLEncryptor(const SSLCipherSharedPtr& cipher) : ssl_cipher_(cipher)
{
}
std::unique_ptr<std::uint8_t[]> SSLEncryptor::generate_key_material(const MaterialPtr& material)
{
// Create the material array
auto materials = material->generate();
// Concat the materials
std::ostringstream imploded;
std::copy(materials.begin(), materials.end(), std::ostream_iterator<std::string>(imploded, ""));
// Perform MGF1 to get the key based on the cipher key length
// We base it off SHA1 for now
// Prepare the out buffer
auto mask_size = ssl_cipher_->key_length();
auto masked = std::make_unique<std::uint8_t[]>(mask_size + 1);
// Output length
std::size_t out_len = 0;
// Digest used
auto digest = std::make_unique<Sha256Digest>();
auto md_len = digest->length() * 2;
// Make sure we dont exceed length
if (mask_size + md_len < md_len)
{
throw std::runtime_error("Key generation size exceeded");
}
// Insert the starting key
digest->update(imploded.str());
std::uint8_t mgf_counter[4] = {0};
// Roll out until size reaches mask
for (int i = 0; out_len < mask_size; i++)
{
mgf_counter[0] = (std::uint8_t)((i >> 24) & 255);
mgf_counter[1] = (std::uint8_t)((i >> 16) & 255);
mgf_counter[2] = (std::uint8_t)((i >> 8) & 255);
mgf_counter[3] = (std::uint8_t)(i & 255);
auto cloned = digest->clone();
cloned->update((std::uint8_t*)mgf_counter, 4);
auto out_str = cloned->finalize();
if (out_len + md_len <= mask_size)
{
std::memcpy(masked.get() + out_len, out_str.c_str(), md_len);
out_len += out_str.size();
}
else
{
std::memcpy(masked.get() + out_len, out_str.c_str(), mask_size - out_len);
out_len = mask_size;
}
Encryptor::secure_zeromem(out_str);
}
return masked;
}
std::string SSLEncryptor::encrypt(const std::string& message, const MaterialPtr& material)
{
if (!material)
{
throw std::runtime_error("Invalid encryption parameters given");
}
int out_len = message.size() + ssl_cipher_->block_size();
int temp_len = 0;
std::vector<std::uint8_t> out_str(out_len, 0);
std::vector<std::uint8_t> iv(ssl_cipher_->iv_length(), 0); // Temporary IV set to 0 for now
std::unique_ptr<EVP_CIPHER_CTX, std::function<void(EVP_CIPHER_CTX*)>> ctx(
EVP_CIPHER_CTX_new(), [](EVP_CIPHER_CTX* ctx) { EVP_CIPHER_CTX_free(ctx); });
EVP_CIPHER_CTX_init(ctx.get());
auto key = std::move(generate_key_material(material));
if (!EVP_CipherInit_ex(ctx.get(), ssl_cipher_->cipher(), nullptr, key.get(), iv.data(), 1))
{
throw std::runtime_error("Failed to cipher init");
}
if (!EVP_CipherUpdate(
ctx.get(), &out_str[0], &temp_len, reinterpret_cast<const std::uint8_t*>(&message[0]), message.size()))
{
throw std::runtime_error("Failed to cipher update");
}
out_len = temp_len;
if (!EVP_CipherFinal_ex(ctx.get(), &out_str[out_len], &temp_len))
{
throw std::runtime_error("Failed to cipher finalize");
}
out_len += temp_len;
auto encoded = Base64::base64_encode(std::string(reinterpret_cast<char const*>(&out_str[0]), out_len));
Encryptor::secure_zeromem(out_str);
return encoded;
}
std::size_t SSLEncryptor::decrypt(const std::string& message, const MaterialPtr& material, std::string& out_buffer)
{
if (!material)
{
throw std::runtime_error("Invalid decryption parameters given");
}
auto decoded_message = Base64::base64_decode(message);
int out_len = decoded_message.size() + ssl_cipher_->block_size();
int temp_len = 0;
std::vector<std::uint8_t> out_str(out_len, 0);
std::vector<std::uint8_t> iv(ssl_cipher_->iv_length(), 0); // Temporary IV set to 0 for now
std::unique_ptr<EVP_CIPHER_CTX, std::function<void(EVP_CIPHER_CTX*)>> ctx(
EVP_CIPHER_CTX_new(), [](EVP_CIPHER_CTX* ctx) { EVP_CIPHER_CTX_free(ctx); });
EVP_CIPHER_CTX_init(ctx.get());
auto key = generate_key_material(material);
if (!EVP_CipherInit_ex(ctx.get(), ssl_cipher_->cipher(), nullptr, key.get(), iv.data(), 0))
{
throw std::runtime_error("Failed to cipher init");
}
if (!EVP_CipherUpdate(ctx.get(),
&out_str[0],
&temp_len,
reinterpret_cast<const std::uint8_t*>(decoded_message.c_str()),
decoded_message.size()))
{
throw std::runtime_error("Failed to cipher update");
}
out_len = temp_len;
if (!EVP_CipherFinal_ex(ctx.get(), &out_str[out_len], &temp_len))
{
//throw std::runtime_error("Failed to cipher finalize");
out_buffer = "not decrypted";
return 0;
}
out_len += temp_len;
Encryptor::secure_zeromem(decoded_message);
out_buffer = std::string(out_str.begin(), out_str.begin() + out_len);
Encryptor::secure_zeromem(out_str);
return out_len;
}
} // namespace octo::encryption::ssl

View File

@@ -0,0 +1,60 @@
/**
* @file sym-encrypt-layer-strategy.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include "octo-encryption-cpp/encryptors/sym-encrypt-layer-strategy.hpp"
#include <stdexcept>
namespace octo::encryption
{
void SymEncryptZeroLayerStrategy::encrypt(const std::string& plain_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& ciphered_string) const
{
ciphered_string = plain_string;
}
std::size_t SymEncryptZeroLayerStrategy::decrypt(const std::string& ciphered_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& plain_string) const
{
plain_string = ciphered_string;
return plain_string.size();
}
void SymEncryptOneLayerStrategy::encrypt(const std::string& plain_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& ciphered_string) const
{
if (!material || !encryptor)
{
throw std::runtime_error("Cannot encrypt with one layer, material or encryptor are invalid");
}
ciphered_string = encryptor->encrypt(plain_string, material);
}
std::size_t SymEncryptOneLayerStrategy::decrypt(const std::string& ciphered_string,
const MaterialPtr& material,
const EncryptorPtr& encryptor,
std::string& plain_string) const
{
if (!material || !encryptor)
{
throw std::runtime_error("Cannot decrypt with one layer, material or encryptor are invalid");
}
return encryptor->decrypt(ciphered_string, material, plain_string);
}
} // namespace octo::encryption

31
src/secure-random.cpp Normal file
View File

@@ -0,0 +1,31 @@
/**
* @file secure-random.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include "octo-encryption-cpp/secure-random.hpp"
#include <openssl/rand.h>
#include <vector>
namespace octo::encryption
{
std::vector<std::uint8_t> SecureRandom::generate_random(std::size_t size)
{
if (size == 0)
{
return std::vector<std::uint8_t>();
}
std::vector<std::uint8_t> v(size, 0);
if (!RAND_bytes(&v[0], size))
{
return std::vector<std::uint8_t>();
}
return v;
}
} // namespace octo::encryption

27
unittests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,27 @@
FIND_PACKAGE(Catch2 REQUIRED CONFIG)
# UT definition
ADD_EXECUTABLE(octo-encryption-cpp-tests
src/base64-tests.cpp
src/ssl-digests-tests.cpp
src/ssl-encryptors-tests.cpp
src/encrypted-string-tests.cpp
src/test.cpp
)
# Properties
SET_TARGET_PROPERTIES(octo-encryption-cpp-tests PROPERTIES CXX_STANDARD 17 POSITION_INDEPENDENT_CODE ON)
TARGET_LINK_LIBRARIES(octo-encryption-cpp-tests
octo-encryption-cpp
Catch2::Catch2
# System Libraries
$<$<PLATFORM_ID:Linux>:pthread>
)
# Discover tests
INCLUDE(CTest)
INCLUDE(Catch)
CATCH_DISCOVER_TESTS(octo-encryption-cpp-tests)

View File

@@ -0,0 +1,109 @@
/**
* @file base64-tests.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include <catch2/catch_all.hpp>
#include "../../include/octo-encryption-cpp/base64.hpp"
TEST_CASE("Encoding Tests", "[base64]")
{
SECTION("Basic Encoding")
{
std::string text = "This is some text";
REQUIRE(octo::encryption::Base64::base64_encode(text) == "VGhpcyBpcyBzb21lIHRleHQ=");
}
SECTION("Empty Encoding")
{
std::string text = "";
REQUIRE(octo::encryption::Base64::base64_encode(text) == "");
}
}
TEST_CASE("Decoding Tests", "[base64]")
{
SECTION("Basic Decoding")
{
std::string text = "VGhpcyBpcyBzb21lIHRleHQ=";
REQUIRE(octo::encryption::Base64::base64_decode(text) == "This is some text");
}
SECTION("Empty Decoding")
{
std::string text = "";
REQUIRE(octo::encryption::Base64::base64_decode(text) == "");
}
}
TEST_CASE("Encoding Decoding Tests", "[base64]")
{
auto s = GENERATE("SomePassword",
"Some_Password",
"Some###Password",
"Djr57822XoLm$^&",
"Djr57822XoLmqwdqwdqw",
"1234567890AbCdEf#@",
"Some Spaces Password For Shtivi 123 @#$^",
"KEKBUR",
"12eqfihfefeiqfh",
"A",
"AB",
"ABC",
"ABCD",
"ABCDE",
"ABCDEF",
"ABCDEFG",
"ABCDEFGH",
"ABCDEFGHI",
"ABCDEFGHIJ",
"ABCDEFGHIJK",
"ABCDEFGHIJKL",
"ABCDEFGHIJKLM",
"ABCDEFGHIJKLMN",
"ABCDEFGHIJKLMNO",
"ABCDEFGHIJKLMNOP",
"ABCDEFGHIJKLMNOPQ",
"ABCDEFGHIJKLMNOPQR",
"ABCDEFGHIJKLMNOPQRS",
"ABCDEFGHIJKLMNOPQRST",
"ABCDEFGHIJKLMNOPQRSTU",
"ABCDEFGHIJKLMNOPQRSTUV",
"ABCDEFGHIJKLMNOPQRSTUVW",
"ABCDEFGHIJKLMNOPQRSTUVWX",
"ABCDEFGHIJKLMNOPQRSTUVWXY",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"ABCDEFGHIJKLMNOPQRSTUVWXYZa",
"ABCDEFGHIJKLMNOPQRSTUVWXYZab",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabc",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcd",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmno",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopq",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
"&尙\\x8c<EFBFBD>\t<EFBFBD>T5<EFBFBD>dT!<21><>");
std::string encoded_text = octo::encryption::Base64::base64_encode(s);
REQUIRE(octo::encryption::Base64::base64_decode(encoded_text) == s);
}

View File

@@ -0,0 +1,70 @@
/**
* @file encrypted-string-tests.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include <catch2/catch_all.hpp>
#include "../../include/octo-encryption-cpp/encryptors/encrypted-string.hpp"
//#include "octo-encryption-cpp/encryptors/ssl/ssl-encryptor.hpp"
#include "../../include/octo-encryption-cpp/encryptors/materials/simple-material.hpp"
#include "../../include/octo-encryption-cpp/encryptors/ssl/ssl-encryptor.hpp"
TEST_CASE("Encryption Decryption", "[encrypted-string]")
{
std::string input_plain_string("Hello World!");
auto encryptor = std::make_shared<octo::encryption::ssl::SSLEncryptor>(
std::make_shared<octo::encryption::ssl::SSLCipher>("AES256"));
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"Key1", "Key2", "Key3"});
SECTION("Set Get")
{
octo::encryption::SingleEncryptedString encrypted_string(encryptor);
// Encryption
encrypted_string.set(input_plain_string, material);
// Decryption
auto output_plain_string = encrypted_string.get();
REQUIRE(input_plain_string == output_plain_string);
}
SECTION("Ctor")
{
octo::encryption::SingleEncryptedString encrypted_string(encryptor);
// Encryption
encrypted_string.set(input_plain_string, material);
octo::encryption::SingleEncryptedString encrypted_string2(encrypted_string.cipher(), material, encryptor);
// Decryption
auto output_plain_string = encrypted_string2.get();
REQUIRE(input_plain_string == output_plain_string);
}
SECTION("Destruct")
{
octo::encryption::SingleEncryptedString encrypted_string(encryptor);
// Encryption
encrypted_string.set(input_plain_string, material);
octo::encryption::SingleEncryptedString encrypted_string2(encrypted_string.cipher(), material, encryptor);
// Decryption
const std::string& output_plain_string = encrypted_string2.get();
REQUIRE(input_plain_string == output_plain_string);
encrypted_string2.destruct();
REQUIRE(std::string("") == output_plain_string);
}
}

View File

@@ -0,0 +1,109 @@
/**
* @file ssl-digests-tests.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#include <catch2/catch_all.hpp>
#include "../../include/octo-encryption-cpp/digests/ssl/ssl-digest.hpp"
namespace
{
constexpr const char SIMPLE_PLAIN_TEXT[] = "This is a plain text to be hashed";
constexpr const char FILE_DATA_CHUNK1[] =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vulputate luctus mattis. Suspendisse fermentum "
"sagittis velit, eu rhoncus tortor cursus eu. In aliquam, turpis nec scelerisque rhoncus, dolor tortor iaculis "
"est, pretium pretium quam velit id purus. Ut porttitor nisi ut eros pulvinar dictum. Aliquam sed nulla fermentum, "
"bibendum libero vel, congue nisl. Proin tristique, turpis vel rutrum gravida, lorem velit feugiat nunc, at "
"euismod odio ipsum sed diam. Phasellus vitae sapien nec tortor gravida semper.";
constexpr const char FILE_DATA_CHUNK2[] =
"Ut euismod fringilla commodo. Morbi dignissim tincidunt odio, id suscipit magna sodales ornare. Nullam a quam "
"vitae lacus tincidunt efficitur. In tristique justo a nisi feugiat interdum a ac erat. Phasellus vel risus magna. "
"Donec ultrices eleifend velit ut bibendum. Integer tempor ligula ut erat efficitur iaculis. Duis sodales porta "
"pretium. Sed lobortis faucibus velit et tempus.";
constexpr const char FILE_DATA_CHUNK3[] =
"Duis non porttitor ipsum, non viverra dolor. Nullam id scelerisque purus. In hac habitasse platea dictumst. Nulla "
"facilisi. Ut at ligula sed ipsum ultrices tempor ullamcorper vel justo. Nulla tempus, tortor vel sollicitudin "
"auctor, odio augue facilisis ex, vitae scelerisque dui quam non eros. Pellentesque vitae nunc orci. Aliquam et "
"consectetur nibh. Donec auctor ut dolor id finibus. In porta tellus vitae nulla eleifend hendrerit. Pellentesque "
"vulputate tempus nisi, nec accumsan quam tristique sed. Vestibulum auctor eleifend pharetra. Donec vulputate, "
"mauris in hendrerit suscipit, lectus quam sollicitudin nulla, pellentesque consectetur dolor lectus ut dui. "
"Integer lobortis, ex nec accumsan bibendum, nisl purus elementum diam, in feugiat arcu tellus eu lacus. Donec "
"neque odio, auctor eget metus ut, venenatis accumsan tellus.";
constexpr const char FILE_DATA_CHUNK4[] =
"Vivamus sit amet ex ut mauris feugiat finibus nec at leo. Donec a enim sem. Nunc rutrum efficitur velit ut "
"luctus. Fusce imperdiet eros sit amet velit iaculis imperdiet. Curabitur suscipit posuere dui, et ultricies "
"neque. Mauris venenatis commodo augue id faucibus. Pellentesque vitae consectetur sem. Aenean quis justo erat. "
"Phasellus ac lacinia diam.";
constexpr const char FILE_DATA_CHUNK5[] =
"Aliquam convallis vehicula hendrerit. Morbi tincidunt sollicitudin fermentum. Cras aliquet ex ut ullamcorper "
"efficitur. Etiam vulputate nisl a arcu volutpat iaculis. Morbi pulvinar tempus ipsum. Maecenas faucibus eros eget "
"aliquet ullamcorper. Etiam eu laoreet magna. Proin eget odio dolor. Suspendisse luctus fermentum magna ac "
"convallis. Suspendisse non sollicitudin nunc. Suspendisse iaculis tellus non orci tristique, sagittis ullamcorper "
"ex commodo. Nunc ac elit eu lorem eleifend blandit vitae non ante.";
} // namespace
const std::pair<octo::encryption::DigestSharedPtr, std::string> digests_simple[] = {
{std::make_shared<octo::encryption::ssl::Sha224Digest>(),
"a00d8a2dc0678544528f769be713d5dc10ffbfe04e31efd1543ad0d0"},
{std::make_shared<octo::encryption::ssl::Sha256Digest>(),
"1b05ce399c8181803aa0e6717c23987d5104c9f32565685a68fa1babadf6947e"},
{std::make_shared<octo::encryption::ssl::Sha384Digest>(),
"de6574e153e579da191b989dcf38be25a8f20266e3ea2812eabef740d866a768ce1cec8accb8606ef504d07ba0a2439f"},
{std::make_shared<octo::encryption::ssl::Sha512Digest>(),
"46454dea35e4e58812ec7db8d424a50f871f66af6ab9cfc5c3fa2f4e9b1160c330ddbd72811db1765598051b6eafe2258e1a9fe6ce489f067"
"e0a2840ba55a5a4"}};
const std::pair<octo::encryption::DigestSharedPtr, std::string> digests_empty[] = {
{std::make_shared<octo::encryption::ssl::Sha224Digest>(),
"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"},
{std::make_shared<octo::encryption::ssl::Sha256Digest>(),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
{std::make_shared<octo::encryption::ssl::Sha384Digest>(),
"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"},
{std::make_shared<octo::encryption::ssl::Sha512Digest>(),
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a"
"538327af927da3e"}};
const std::pair<octo::encryption::DigestSharedPtr, std::string> digests_chunks[] = {
{std::make_shared<octo::encryption::ssl::Sha224Digest>(),
"040abc9ba69bc339119b9e58ab69f7b4b960a62a0f146aafdeb358ac"},
{std::make_shared<octo::encryption::ssl::Sha256Digest>(),
"46d5f77048d84305a937649ddc379052a3394cb229055d3f5443782c8f2c306d"},
{std::make_shared<octo::encryption::ssl::Sha384Digest>(),
"56bb301833145fe31a8b03ded17f6bdaa54e3d9d7433cbf7c4283b44b0a29fba2540bc5128303492ae1ef0f8dbcb38b6"},
{std::make_shared<octo::encryption::ssl::Sha512Digest>(),
"594bc4c8127b4b62333a663425bf2a5197ebcf70aef072b6b8f0a5a0ef2829065dda2b11b673e77d7e68ef7192ec2f9d40fe39df8d2e0079c"
"f20c05f3355b098"}};
TEST_CASE("Different Digests", "[digest]")
{
SECTION("Digests Validation")
{
auto s = GENERATE(digests_simple);
s->first->update(SIMPLE_PLAIN_TEXT);
REQUIRE(s->first->finalize() == s->second);
}
SECTION("Empty Validation")
{
auto s = GENERATE(digests_empty);
REQUIRE(s->first->finalize() == s->second);
}
SECTION("Chunks Validation")
{
auto s = GENERATE(digests_chunks);
s->first->update(FILE_DATA_CHUNK1);
s->first->update(FILE_DATA_CHUNK2);
s->first->update(FILE_DATA_CHUNK3);
s->first->update(FILE_DATA_CHUNK4);
s->first->update(FILE_DATA_CHUNK5);
REQUIRE(s->first->finalize() == s->second);
}
}

View File

@@ -0,0 +1,113 @@
#include <catch2/catch_all.hpp>
#include "../../include/octo-encryption-cpp/encryptors/ssl/ssl-encryptor.hpp"
#include "../../include/octo-encryption-cpp/encryptors/materials/simple-material.hpp"
#include "../../include/octo-encryption-cpp/encryptors/material.hpp"
namespace
{
constexpr const auto SMALLSTRING = "abc";
constexpr const auto LONGSTRING = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
}
void test_encrypt_decrypt(const std::string & value,
octo::encryption::ssl::SSLEncryptor & encryptor,
const octo::encryption::MaterialPtr & material)
{
std::string encrypted = encryptor.encrypt(value, material);
std::string output;
REQUIRE(encryptor.decrypt(encrypted, material, output) == value.size());
REQUIRE(value == output);
}
TEST_CASE("Different Encryptions", "[encryptors]")
{
auto materials = {
std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"Key1"}),
std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"Key2"}),
std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"VeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongMaterial"}),
std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"K"}),
std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"E(HFWQ(FH(WE@FH@$(FH@FH(HF@("})
};
auto encryptor = octo::encryption::ssl::SSLEncryptor(std::make_shared<octo::encryption::ssl::SSLCipher>("AES256"));
SECTION("Different Materials Empty String")
{
for(auto & m : materials)
{
test_encrypt_decrypt("", encryptor, m);
}
}
SECTION("Different Materials Small String")
{
for(auto & m : materials)
{
test_encrypt_decrypt(SMALLSTRING, encryptor, m);
}
}
SECTION("Different Materials Long String")
{
for(auto & m : materials)
{
test_encrypt_decrypt(LONGSTRING, encryptor, m);
}
}
SECTION("Multiple Materials")
{
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"Key1", "Key2", "Key3"});
test_encrypt_decrypt(LONGSTRING, encryptor, material);
}
SECTION("Long Multiple Material")
{
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"VeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongMaterial",
"VeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongMaterial12312312312",
"VeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongMaterial9q302ye80q2390q89yrq23978r9qwauegsgfaeofg97e8aofgq3984g2493fg2943f"});
test_encrypt_decrypt(LONGSTRING, encryptor, material);
}
SECTION("Different Algorithms")
{
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"Key1", "Key2", "Key3"});
auto algs = {"AES128", "AES192", "AES256"};
for(auto & alg : algs)
{
auto e = octo::encryption::ssl::SSLEncryptor(std::make_shared<octo::encryption::ssl::SSLCipher>(alg));
test_encrypt_decrypt(LONGSTRING, e, material);
}
}
}
TEST_CASE("Encryption", "[encryptor]")
{
auto encryptor = octo::encryption::ssl::SSLEncryptor(std::make_shared<octo::encryption::ssl::SSLCipher>("AES256"));
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"Key1", "Key2", "Key3"});
SECTION("Encryption Same Values")
{
std::string encrypted1 = encryptor.encrypt(LONGSTRING, material);
std::string encrypted2 = encryptor.encrypt(LONGSTRING, material);
REQUIRE(encrypted1 == encrypted2);
}
}
TEST_CASE("Decryption", "[encryptor]")
{
auto encryptor = octo::encryption::ssl::SSLEncryptor(std::make_shared<octo::encryption::ssl::SSLCipher>("AES256"));
SECTION("Decryption Right Material")
{
std::string plain = "A9BE11F3762F6BD386D97C7F7F56408EE7073BD2FDE7FDD4418C85DBF1FFE7B9B0E33E4CA8E68D425D7A6FCFC69F50C28D04B90967B7A701496DD314405DCB56";
std::string encrypted ="/R1VN7Qh9wndVE9ylGJqEobuNB5Wmx3WhnE2ncGJ/0K+0manObk22TiZjVrfMAnwh6itWfS+MyAzYAuCr1yD0mZXtKNwPfzROUMhgDIdMP1U7RWt4SZTKboCrl4t5ePS7bzQiNcTKgq4Y5Shnps2Im1rRdm8WzXy9db9P/Bu61vRfCsHhAPNijvrRYsrKJw5";
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"HostName123abc"});
std::string output;
REQUIRE(encryptor.decrypt(encrypted, material, output) == plain.size());
REQUIRE(plain == output);
}
SECTION("Decryption Wrong Material")
{
std::string encrypted ="/R1VN7Qh9wndVE9ylGJqEobuNB5Wmx3WhnE2ncGJ/0K+0manObk22TiZjVrfMAnwh6itWfS+MyAzYAuCr1yD0mZXtKNwPfzROUMhgDIdMP1U7RWt4SZTKboCrl4t5ePS7bzQiNcTKgq4Y5Shnps2Im1rRdm8WzXy9db9P/Bu61vRfCsHhAPNijvrRYsrKJw5";
auto material = std::make_shared<octo::encryption::SimpleMaterial>(std::vector<std::string>{"HostName123abcWRONG"});
std::string output;
REQUIRE_THROWS(encryptor.decrypt(encrypted, material, output));
}
}

19
unittests/src/test.cpp Normal file
View File

@@ -0,0 +1,19 @@
/**
* @file test.cpp
* @author ofir iluz (iluzofir@gmail.com)
* @brief
* @version 0.1
* @date 2022-08-11
*
* @copyright Copyright (c) 2022
*
*/
#define CATCH_CONFIG_RUNNER
#include <catch2/catch_all.hpp>
int main( int argc, char* argv[] )
{
int result = Catch::Session().run(argc, argv);
return result;
}