Tidied up example/static test executables

This commit is contained in:
Leonetienne 2022-05-26 18:24:44 +02:00
parent e7c1e17e2c
commit c0418766d9
No known key found for this signature in database
GPG Key ID: C33879CD92E9708C
20 changed files with 574 additions and 69 deletions

6
.gitmodules vendored
View File

@ -7,3 +7,9 @@
[submodule "GeneralUtility"]
path = GeneralUtility
url = https://gitea.leonetienne.de/leonetienne/GeneralUtility.git
[submodule "GCryptLib/exec/Eule"]
path = GCryptLib/exec/Eule
url = https://gitea.leonetienne.de/leonetienne/Eule.git
[submodule "GCryptLib/exec/BmpPP"]
path = GCryptLib/exec/BmpPP
url = https://gitea.leonetienne.de/leonetienne/BmpPP.git

View File

@ -40,7 +40,7 @@ target_compile_options(test PRIVATE
)
## Move test images to build dir
## Move test assest to build dir
ADD_CUSTOM_COMMAND(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
@ -48,21 +48,39 @@ ADD_CUSTOM_COMMAND(
)
##############
# Executable #
##############
FILE(GLOB exec_src exec/*.cpp)
add_executable(exec
${exec_src}
)
target_link_libraries(exec ${PROJECT_NAME})
target_include_directories(exec PRIVATE
###############
# Executables #
###############
FILE(GLOB bmpp_src exec/BmpPP/BmpPP/src/*.cpp)
FILE(GLOB eule_src exec/Eule/Eule/src/*.cpp)
add_compile_definitions(_EULE_NO_INTRINSICS_)
include_directories(
include
exec/BmpPP/BmpPP/include
exec/Eule/Eule/include
)
target_compile_options(exec PRIVATE
-Werror
-fdiagnostics-color=always
## Move exec assets to build dir
ADD_CUSTOM_COMMAND(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/exec/execAssets/ $<TARGET_FILE_DIR:${PROJECT_NAME}>/execAssets/
)
function(DECLARE_EXEC_EXAMPLE name)
add_executable(example-${name} exec/${name}.cpp ${bmpp_src} ${eule_src})
target_link_libraries(example-${name} ${PROJECT_NAME})
target_compile_options(example-${name} PRIVATE -Werror -fdiagnostics-color=always)
endfunction()
# These are the names of the cpp files in /exec/, without the ".cpp".
DECLARE_EXEC_EXAMPLE(encrypt-decrypt-files)
DECLARE_EXEC_EXAMPLE(encrypt-decrypt-strings)
DECLARE_EXEC_EXAMPLE(benchmark-encryption)
DECLARE_EXEC_EXAMPLE(benchmark-prng)
DECLARE_EXEC_EXAMPLE(visualize-singleblock-diffusion)
DECLARE_EXEC_EXAMPLE(visualize-multiblock-diffusion)
DECLARE_EXEC_EXAMPLE(visualize-extreme-input-diffusion)
DECLARE_EXEC_EXAMPLE(visualize-prng-distribution)
DECLARE_EXEC_EXAMPLE(visualize-hashing-distribution)

View File

@ -0,0 +1,23 @@
#ifndef GCRYPTEXAMPLE_BENCHMARK_H
#define GCRYPTEXAMPLE_BENCHMARK_H
#include <functional>
#include <chrono>
#include <iostream>
void Benchmark(const std::string& brief, std::function<void()> toBenchmark) {
std::cout << "Benchmarking " << brief << "..." << std::endl;
auto start = std::chrono::steady_clock::now();
toBenchmark();
auto end = std::chrono::steady_clock::now();
double seconds = (double)std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / 1000.0;
std::cout << seconds << " seconds." << std::endl << std::endl;
return;
}
#endif

1
GCryptLib/exec/BmpPP Submodule

@ -0,0 +1 @@
Subproject commit 522f9551ae31215cf63fcad88cacbfc8c818ccaf

1
GCryptLib/exec/Eule Submodule

@ -0,0 +1 @@
Subproject commit 1bfd756aa8bd1d484857735d63b4fdf8a15bbed5

View File

@ -0,0 +1,58 @@
#ifndef GCRYPTEXAMPLE_VISUALIZE_H
#define GCRYPTEXAMPLE_VISUALIZE_H
#include <GCrypt/Block.h>
#include <BmpPP/Bmp.h>
#include <string>
using namespace Leonetienne::GCrypt;
using namespace Leonetienne::Eule;
using namespace Leonetienne::BmpPP;
void VisualizeBlock(const Block& block, const std::string& name) {
BMP bmp(Vector2i(32, 16), Colormode::RGB);
std::size_t i = 0;
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
const std::uint8_t pixel = block.GetBit(i) == false ? 255 : 0;
bmp.SetPixel(Vector2i(x, y), pixel);
i++;
}
bmp.Write(name);
return;
}
// size.x*size.y MUST equal blocks.size() * Block::BLOCK_SIZE_BITS. That should be, by defalt blocks.size * 512.
void VisualizeBlocks(const std::vector<Block>& blocks, const Vector2i& size, const std::string& name) {
//! A bit of error checking...
if (size.x*size.y != blocks.size() * Block::BLOCK_SIZE_BITS) {
throw std::invalid_argument("Supplied unfitting widht/height for visualization. Does not fit bits!");
}
BMP bmp(size, Colormode::RGB);
std::size_t i = 0;
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
const std::size_t blockIndex = i / Block::BLOCK_SIZE_BITS;
const std::size_t relBitIndex = i - blockIndex * Block::BLOCK_SIZE_BITS;
const std::uint8_t pixel = blocks[blockIndex].GetBit(relBitIndex) == false ? 255 : 0;
bmp.SetPixel(Vector2i(x, y), pixel);
i++;
}
bmp.Write(name);
return;
}
#endif

View File

@ -0,0 +1,21 @@
#include <GCrypt/GWrapper.h>
#include "Benchmark.h"
using namespace Leonetienne::GCrypt;
int main() {
Benchmark(
"file encryption",
[]() {
GWrapper::EncryptFile(
"./execAssets/big-testfile.bmp",
"./execAssets/testimage.bmp.crypt",
Key::FromPassword("password1")
);
}
);
return 0;
}

View File

@ -0,0 +1,42 @@
#include <GCrypt/GPrng.h>
#include <iostream>
#include "Benchmark.h"
using namespace Leonetienne::GCrypt;
int main() {
Benchmark(
"generating 1.000.000 32-bit uints using prng.GetRandom<uint32_t>()",
[]() {
GPrng prng(Key::Random());
for (int i = 0; i < 1000000; i++) {
prng.GetRandom<std::uint32_t>();
}
}
);
Benchmark(
"generating 1.000.000 uint32_t using prng()",
[]() {
GPrng prng(Key::Random());
for (int i = 0; i < 1000000; i++) {
prng();
}
}
);
Benchmark(
"generating 100.000 data blocks using prng.GetBlock()",
[]() {
GPrng prng(Key::Random());
for (int i = 0; i < 100000; i++) {
prng.GetBlock();
}
}
);
return 0;
}

View File

@ -0,0 +1,25 @@
#include <GCrypt/GWrapper.h>
#include <iostream>
using namespace Leonetienne::GCrypt;
int main() {
std::cout << "Example on how to encrypt & decrypt any file:" << std::endl;
// Encrypt
GWrapper::EncryptFile(
"./execAssets/testimage.bmp",
"./execAssets/testimage.bmp.crypt",
Key::FromPassword("password1")
);
// Decrypt
GWrapper::DecryptFile(
"./execAssets/testimage.bmp.crypt",
"./execAssets/testimage.bmp.clear.bmp",
Key::FromPassword("password1"
));
return 0;
}

View File

@ -0,0 +1,30 @@
#include <GCrypt/GWrapper.h>
#include <iostream>
using namespace Leonetienne::GCrypt;
int main() {
std::cout << "Example on how to encrypt & decrypt strings:" << std::endl;
const std::string cleartext = "Hello, World :3";
std::cout << "Cleartext: " << cleartext << std::endl;
// Encrypt
const std::string ciphertext = GWrapper::EncryptString(
cleartext,
Key::FromPassword("password1")
);
std::cout << "Ciphertext: " << ciphertext << std::endl;
// Decrypt
const std::string decrypted = GWrapper::DecryptString(
ciphertext,
Key::FromPassword("password1")
);
std::cout << "Decrypted: " << decrypted << std::endl;
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

@ -1,46 +0,0 @@
#include <iostream>
#include <GCrypt/GWrapper.h>
#include <GCrypt/SecureBitset.h>
#include <GCrypt/Util.h>
#include <GCrypt/InitializationVector.h>
#include <GCrypt/Key.h>
using namespace Leonetienne::GCrypt;
void ExampleString() {
std::cout << "Example on how to encrypt & decrypt a string:" << std::endl;
// Get some string
const std::string input = "I am a super secret message!";
std::cout << input << std::endl;
// Encrypt
const std::string encrypted = GWrapper::EncryptString(input, Key::FromPassword("password1"));
std::cout << encrypted << std::endl;
// Decrypt
const std::string decrypted = GWrapper::DecryptString(encrypted, Key::FromPassword("password1"));
std::cout << decrypted << std::endl;
return;
}
void ExampleFiles() {
std::cout << "Example on how to encrypt & decrypt any file:" << std::endl;
// Encrypt
GWrapper::EncryptFile("main.cpp", "main.cpp.crypt", Key::FromPassword("password1"));
// Decrypt
GWrapper::DecryptFile("main.cpp.crypt", "main.cpp.clear", Key::FromPassword("password1"));
return;
}
int main() {
ExampleString();
//ExampleFiles();
return 0;
}

View File

@ -0,0 +1,54 @@
#include <iostream>
#include <GCrypt/GWrapper.h>
#include <GCrypt/Key.h>
#include <GCrypt/Util.h>
#include <BmpPP/Bmp.h>
#include "Visualize.h"
const std::string execName = "visualize-extreme-input-diffusion";
using namespace Leonetienne::GCrypt;
using namespace Leonetienne::BmpPP;
using namespace Leonetienne::Eule;
int main() {
// These are magic values, which work for this specific input string.
// If you want to try another string, get the size of all blocks in bits (it gets printed),
// and find two integer factors which factor up to it. These are your images width, and height.
const Vector2i visualizationDimension = Vector2i(56, 64);
// Create a key
// The key is almost just zeores (it doesn't have an IV, so what you see is what goes in the cipher.)
// In case you're wondering, I can tell you right now that an all-zero input with an all-zero key will result in an all-zero ciphertext.
Key key;
key.Reset();
key.SetBit(199, true);
VisualizeBlock(key, execName+"-key.bmp");
// Create our input blocks
// All the input blocks are just zeroes!
std::vector<Block> input_blocks;
input_blocks.resize(7);
for (Block& block : input_blocks) {
block.Reset();
}
std::cout << "Input size is " << input_blocks.size() * Block::BLOCK_SIZE_BITS << " bits long." << std::endl;
VisualizeBlocks(input_blocks, visualizationDimension, execName+"-input.bmp");
// Encrypt it
std::vector<Block> ciphertext_blocks = GWrapper::CipherBlocks(input_blocks, key, GCipher::DIRECTION::ENCIPHER);
VisualizeBlocks(ciphertext_blocks, visualizationDimension, execName+"-output.bmp");
// Now flip a single bit in the input
input_blocks[3].FlipBit(156);
VisualizeBlocks(input_blocks, visualizationDimension, execName+"-input-flip.bmp");
// Encrypt it again
ciphertext_blocks = GWrapper::CipherBlocks(input_blocks, key, GCipher::DIRECTION::ENCIPHER);
VisualizeBlocks(ciphertext_blocks, visualizationDimension, execName+"-output-flip.bmp");
return 0;
}

View File

@ -0,0 +1,34 @@
#include <iostream>
#include <GCrypt/GHash.h>
#include <BmpPP/Bmp.h>
#include "Visualize.h"
const std::string execName = "visualize-hashing-distribution";
using namespace Leonetienne::GCrypt;
using namespace Leonetienne::BmpPP;
using namespace Leonetienne::Eule;
void HashAndVisualize(const Block& b, const std::string filename) {
GHash hasher;
hasher.DigestBlock(b);
VisualizeBlock(hasher.GetHashsum(), filename);
}
int main() {
// Get some random input
Block a;
a.FromTextString("Hello, World :3");
VisualizeBlock(a, execName+"-input-a.bmp");
HashAndVisualize(a, execName+"-output-a.bmp");
// Now flip a bit
Block b = a;
b.FlipBit(4);
VisualizeBlock(b, execName+"-input-b.bmp");
HashAndVisualize(b, execName+"-output-b.bmp");
return 0;
}

View File

@ -0,0 +1,45 @@
#include <iostream>
#include <GCrypt/GWrapper.h>
#include <GCrypt/Key.h>
#include <GCrypt/Util.h>
#include <BmpPP/Bmp.h>
#include "Visualize.h"
const std::string execName = "visualize-multiblock-diffusion";
using namespace Leonetienne::GCrypt;
using namespace Leonetienne::BmpPP;
using namespace Leonetienne::Eule;
int main() {
// These are magic values, which work for this specific input string.
// If you want to try another string, get the size of all blocks in bits (it gets printed),
// and find two integer factors which factor up to it. These are your images width, and height.
const Vector2i visualizationDimension = Vector2i(56, 64);
// Create a key
const Key key = Key::Random();
VisualizeBlock(key, execName+"-key.bmp");
// Create our input blocks
const std::string input = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
std::vector<Block> input_blocks = StringToBitblocks(input);
std::cout << "Input size is " << input_blocks.size() * Block::BLOCK_SIZE_BITS << " bits long." << std::endl;
VisualizeBlocks(input_blocks, visualizationDimension, execName+"-input.bmp");
// Encrypt it
std::vector<Block> ciphertext_blocks = GWrapper::CipherBlocks(input_blocks, key, GCipher::DIRECTION::ENCIPHER);
VisualizeBlocks(ciphertext_blocks, visualizationDimension, execName+"-output.bmp");
// Now flip a single bit in the input
input_blocks[3].FlipBit(156);
VisualizeBlocks(input_blocks, visualizationDimension, execName+"-input-flip.bmp");
// Encrypt it again
ciphertext_blocks = GWrapper::CipherBlocks(input_blocks, key, GCipher::DIRECTION::ENCIPHER);
VisualizeBlocks(ciphertext_blocks, visualizationDimension, execName+"-output-flip.bmp");
return 0;
}

View File

@ -0,0 +1,146 @@
#include <iostream>
#include <GCrypt/Key.h>
#include <GCrypt/GPrng.h>
#include <BmpPP/Bmp.h>
#include "Benchmark.h"
const std::string execName = "visualize-prng-distribution";
using namespace Leonetienne::GCrypt;
using namespace Leonetienne::BmpPP;
using namespace Leonetienne::Eule;
int main() {
// Black/white
Benchmark(
"black/white - GetBit()",
[]() {
Key seed = Key::Random();
BMP bmp(Vector2i(800, 800), Colormode::RGB);
GPrng prng(seed);
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
const std::uint8_t pixel = prng.GetBit() ? 255 : 0;
bmp.SetPixel(Vector2i(x, y), pixel);
}
bmp.Write(execName+"-blackwhite.bmp");
}
);
// Grayscale (using GetRandom<>)
Benchmark(
"grayscale - GetRandom<std::uint8_t>()",
[]() {
Key seed = Key::Random();
BMP bmp(Vector2i(800, 800), Colormode::RGB);
GPrng prng(seed);
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
const std::uint8_t pixel = prng.GetRandom<std::uint8_t>();
bmp.SetPixel(Vector2i(x, y), pixel);
}
bmp.Write(execName+"-getrandom-grayscale.bmp");
}
);
// Grayscale (using operator()) (this one returns a whole uint32)
Benchmark(
"grayscale - operator()",
[]() {
Key seed = Key::Random();
BMP bmp(Vector2i(800, 800), Colormode::RGB);
GPrng prng(seed);
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
const std::uint8_t pixel = prng() % 256;
bmp.SetPixel(Vector2i(x, y), pixel);
}
bmp.Write(execName+"-operator()-grayscale.bmp");
}
);
// Color (using GetRandom<>)
Benchmark(
"color - GetRandom<uint8_t>()",
[]() {
Key seed = Key::Random();
BMP bmp(Vector2i(800, 800), Colormode::RGB);
GPrng prng(seed);
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
const std::uint8_t r = prng.GetRandom<std::uint8_t>();
const std::uint8_t g = prng.GetRandom<std::uint8_t>();
const std::uint8_t b = prng.GetRandom<std::uint8_t>();
bmp.SetPixel(Vector2i(x, y), r, g, b);
}
bmp.Write(execName+"-getrandom-color.bmp");
}
);
// Color (using operator()) (this one returns a whole uint32)
Benchmark(
"color - operator()",
[]() {
Key seed = Key::Random();
BMP bmp(Vector2i(800, 800), Colormode::RGB);
GPrng prng(seed);
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
const std::uint8_t r = prng() % 256;
const std::uint8_t g = prng() % 256;
const std::uint8_t b = prng() % 256;
bmp.SetPixel(Vector2i(x, y), r, g, b);
}
bmp.Write(execName+"-operator()-color.bmp");
}
);
// Color (using GetBlock())
//(this one returns a derivation of the current hashsum, without using up randomness)
Benchmark(
"color - GetBlock()",
[]() {
Key seed = Key::Random();
BMP bmp(Vector2i(800, 800), Colormode::RGB);
GPrng prng(seed);
std::size_t bytes_written = 0;
while (bytes_written < bmp.GetPixelbufferSize()) {
const Block block = prng.GetBlock();
std::size_t bytesToCopy = 0;
if (bmp.GetPixelbufferSize() - bytes_written < Block::BLOCK_SIZE) {
bytesToCopy = bmp.GetPixelbufferSize() - bytes_written;
}
else {
bytesToCopy = Block::BLOCK_SIZE;
}
memcpy(
(char*)bmp.GetPixelbuffer().data() + bytes_written,
(char*)block.Data(),
bytesToCopy
);
bytes_written += bytesToCopy;
}
bmp.Write(execName+"-getblock-color.bmp");
}
);
return 0;
}

View File

@ -0,0 +1,45 @@
#include <iostream>
#include <GCrypt/GWrapper.h>
#include <GCrypt/Key.h>
#include <BmpPP/Bmp.h>
#include "Visualize.h"
const std::string execName = "visualize-singleblock-diffusion";
using namespace Leonetienne::GCrypt;
using namespace Leonetienne::BmpPP;
using namespace Leonetienne::Eule;
int main() {
// Create input block
const std::string input_str = "Hello :3";
Block input;
input.FromTextString(input_str);
VisualizeBlock(input, execName+"-input.bmp");
// Create a key
const Key key = Key::Random();
VisualizeBlock(key, execName+"-key.bmp");
// Create a cipher
GCipher cipher(key, GCipher::DIRECTION::ENCIPHER);
// Encipher our block
Block cipherblock = cipher.Digest(input);
VisualizeBlock(cipherblock, execName+"-output.bmp");
// Now flip a bit in the input
input.FlipBit(35);
VisualizeBlock(input, execName+"-input-flip.bmp");
// Reset our cipher, and encipher the input with a flipped bit
cipher.Initialize(key, GCipher::DIRECTION::ENCIPHER);
// Encipher our block
cipherblock = cipher.Digest(input);
VisualizeBlock(cipherblock, execName+"-output-flip.bmp");
return 0;
}

View File

@ -15,10 +15,10 @@ namespace Leonetienne::GCrypt {
key.FromByteString("nsoCZfvdqpRkeVTt9wzvPR3TT26peOW9E2kTHh3pdPCq2M7BpskvUljJHSrobUTI");
cipher = GCipher(
// The key really does not matter, as it gets changed
// each time before digesting anything.
key,
GCipher::DIRECTION::ENCIPHER
// The key really does not matter, as it gets changed
// each time before digesting anything.
key,
GCipher::DIRECTION::ENCIPHER
);
return;
@ -26,10 +26,11 @@ namespace Leonetienne::GCrypt {
void GHash::DigestBlock(const Block& data) {
// Set the cipher key to the current data to be hashed
cipher.SetKey(Key(data));
cipher.SetKey(data);
// Encipher the current block, and xor it on the current hashsum
// Encipher the current block, and matrix-mult it with the current hashsum
block ^= cipher.Digest(data);
return;
}

View File

@ -26,7 +26,7 @@ namespace Leonetienne::GCrypt {
}
// Return the next bit.
return hasher.GetHashsum()[nextBit++];
return hasher.GetHashsum().GetBit(nextBit++);
}
void GPrng::AdvanceBlock() {
@ -50,8 +50,6 @@ namespace Leonetienne::GCrypt {
// 1) Fetch complete current hashsum (it might have been partially given out already)
// 2) Bitshift it, and matrix-mult it with the seed (that is irreversible)
// That should be a one-way function, and create a new unique block.
// We don't even have to AdvanceBlock(), because we've only given out
// hashsum', not hashsum.
// Performance improvement over the previous method:
// (generating 100.000 blocks):
@ -65,6 +63,9 @@ namespace Leonetienne::GCrypt {
hashsum.ShiftBitsLeftInplace();
hashsum *= seed;
// Advance the block, so that the following block will be a new block
AdvanceBlock();
// Return our hashsum
return hashsum;
}