Compare commits

...

28 Commits

Author SHA1 Message Date
521ec2bc2e
fix git remote ids 2024-09-26 10:26:48 +02:00
Leon Etienne
88a1295383 Install graphviz for doxygen pipelione
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-25 22:18:42 +00:00
Leon Etienne
626ca33536 Fix readme cropping for doxygen
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-25 22:15:33 +00:00
Leon Etienne
535c90b92c Add build status to readme
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-25 21:47:43 +00:00
Leon Etienne
b1abc77f32 Import working drone config
All checks were successful
continuous-integration/drone/push Build is passing
2022-10-25 21:44:05 +00:00
Leon Etienne
827622a0b7 Cicd-test
Some checks failed
continuous-integration/drone/push Build is failing
2022-10-25 20:10:42 +00:00
Leonetienne
d507bd1b2f
Merge branch 'master' of gitea.leonetienne.de:leonetienne/GCrypt 2022-08-12 09:13:10 +02:00
Leonetienne
4561620eac
CLI: Fix typo in option name 2022-08-12 09:12:44 +02:00
Leonetienne
f6b8e9fbad
typo readme 2022-07-07 14:09:26 +02:00
Leonetienne
e5d4211761
Improved tests for block class 2022-06-04 00:01:21 +02:00
Leonetienne
f0456193a9
Adjust makefile doxygen 2022-06-01 21:35:46 +02:00
Leonetienne
656934634b
Fix image alt tag in readme, that screwed with doxygen 2022-06-01 21:01:38 +02:00
Leonetienne
573674a0b7
Update project name in doxygen config 2022-06-01 20:59:26 +02:00
Leonetienne
7410bc1b54
Add docs link to readme 2022-06-01 20:58:31 +02:00
Leonetienne
377099907b
Readme 2022-06-01 19:57:55 +02:00
Leonetienne
9a02c37a68
Readme 2022-06-01 19:56:08 +02:00
Leonetienne
fc6208f08a
Update readme 2022-06-01 19:55:06 +02:00
Leonetienne
afa07d0aca
Merge branch 'master' of gitea.leonetienne.de:leonetienne/GCrypt 2022-06-01 16:54:25 +02:00
Leonetienne
2f5e65b334
A bit of code cleanup 2022-06-01 16:54:14 +02:00
Leonetienne
00d0f81bd9
Fix compiler warning on macos 2022-06-01 15:28:17 +02:00
Leonetienne
f0db047316
Typo readme 2022-06-01 04:01:12 +02:00
Leonetienne
27ebdb8d63
Fixes in cli readme 2022-06-01 03:58:48 +02:00
Leonetienne
4f73996d79
Update help page in cli readme 2022-06-01 03:47:58 +02:00
Leonetienne
35a5c9496d
Wording in help page 2022-06-01 03:46:27 +02:00
Leonetienne
309dacadc8
Adjust links in readme 2022-06-01 03:32:01 +02:00
Leonetienne
74883458ba
Merge branch 'feature/relaunch' into master 2022-06-01 03:30:55 +02:00
Leonetienne
985aca1ef0
Merge branch 'master' of gitea.leonetienne.de:leonetienne/GCrypt 2022-05-20 10:19:45 +02:00
Leonetienne
61577acd9e
Add ideas for cli relaunch 2022-05-17 12:32:30 +02:00
16 changed files with 267 additions and 159 deletions

56
.drone.yml Normal file
View File

@ -0,0 +1,56 @@
kind: pipeline
type: kubernetes
name: cicd-pipeline
steps:
- name: Build docs
image: ubuntu
commands:
- apt-get update
- >-
apt-get
install
make
doxygen
graphviz
-y
- cd "GCryptLib/doxygen"
- make
- name: Deploy docs to production
image: ubuntu
environment:
SSH_PRIV:
from_secret: ssh-priv
SSH_PUB:
from_secret: ssh-pub
KNOWN_HOSTS:
from_secret: known-hosts # this is just $(ssh-keyscan -p 2222 leonetienne.de)
commands:
- apt-get update
- >-
apt-get
install
openssh-client
rsync
-y
- eval "$(ssh-agent -s)"
- mkdir -p ~/.ssh
- echo "$SSH_PRIV" > ~/.ssh/id_ed25519
- echo "$SSH_PUB" > ~/.ssh/id_ed25519.pub
- echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts
- chmod 600 ~/.ssh/id_ed25519
- chmod 644 ~/.ssh/id_ed25519.pub
- chmod 644 ~/.ssh/known_hosts
- ssh-add
- cd "GCryptLib/doxygen"
- >-
rsync
-avz
--recursive
--delete
--delete-excluded
-e
"ssh -o IdentitiesOnly=yes -p 2222"
./build/
doxygen-gcrypt@leonetienne.de:app

12
.gitmodules vendored
View File

@ -1,15 +1,17 @@
[submodule "StringTools"] [submodule "StringTools"]
path = StringTools path = StringTools
url = https://gitea.leonetienne.de/leonetienne/StringTools.git url = https://code.ze.mawtrixx.net/leonetienne/StringTools.git
[submodule "Hazelnupp"] [submodule "Hazelnupp"]
path = Hazelnupp path = Hazelnupp
url = https://gitea.leonetienne.de/leonetienne/Hazelnupp.git url = https://code.ze.mawtrixx.net/leonetienne/Hazelnupp.git
[submodule "GeneralUtility"] [submodule "GeneralUtility"]
path = GeneralUtility path = GeneralUtility
url = https://gitea.leonetienne.de/leonetienne/GeneralUtility.git url = https://code.ze.mawtrixx.net/leonetienne/GeneralUtility.git
[submodule "GCryptLib/exec/Eule"] [submodule "GCryptLib/exec/Eule"]
path = GCryptLib/exec/Eule path = GCryptLib/exec/Eule
url = https://gitea.leonetienne.de/leonetienne/Eule.git url = https://code.ze.mawtrixx.net/leonetienne/Eule.git
[submodule "GCryptLib/exec/BmpPP"] [submodule "GCryptLib/exec/BmpPP"]
path = GCryptLib/exec/BmpPP path = GCryptLib/exec/BmpPP
url = https://gitea.leonetienne.de/leonetienne/BmpPP.git url = https://code.ze.mawtrixx.net/leonetienne/BmpPP.git
[submodule "BmpPP"]
url = https://code.ze.mawtrixx.net/leonetienne/BmpPP.git

View File

@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2022-05-17T08:55:29.265Z" agent="5.0 (X11)" etag="82noNgqBrG7hiBNRM9Jy" version="18.0.6"><diagram id="ngb83caThQZh03zxjPih" name="Page-1">7VpNc+I4EP01VJHDUDYEkhwDJDvMMMXWcNjZuWwJq7G1sS2PLALk169alr9hQwhkApULltpS66Pfe2q5aHQGweoPQSLvG6fgN9oWXTU6w0a7bXdvLPVAyzqxXHdvEoMrGDWNcsOUPYExmn7uglGISw0l575kUdno8DAER5ZsRAi+LDebc788akRcqBmmDvHr1r8YlV66Ciu3fwbmeunItmXeBCRtbAyxRyhfFkydu0ZnIDiXSSlYDcDHzUv3Jel3v+VtNjEBodylw7/Bl88/u/F0YP9Yj9rf5uLrl+4n4+WR+Auz4Ea75yt/fcoeVdHF4pBIgo5CF2LJeKjKPlmDUM/mcDS+SLvMRNojtajZFPyUXFvEZ26ox+z9WuAm9H2Yy7xW7XUc79+B0Fi1748ng6//TEc/71RlxiTa5oIH6CrUi48WEhc8Zwoa7QEGVFIWJkUi3PjCFEOKzYMAKCMS/DU6AtCDSI/hY+Zz50EDWduUO2s4HLfU4ztEQPTYi1AyjN7d5B7doUkAcTyg2G5MYllwpF9LwvyIUAo4/pIp9LUtq3XKsbn1Y67XHUc8jNkMN14xGHFHnF8LJhQi0/hA6Ih1ZND5AOuTXvho3kAyJ11Zap0t5nMQowSI2WAsHyrBQa2fFIrbGzsMcvyNxho1WjFCLg1o9e6uFWz1RqeYhEcQmdEjmiosZLGnOyiYKl64+wXgpburhVWuU7UWfBEiATpDS71eekzCNCIOvl2q80nZPBn4qmarolqFZErpb01UJI8yn/gOVluV1s70Wx18wAOQAnmedrg0km/OPLtn6sv8BOmmJ4hXPD06xkjMqeVmvnNhVwWj7S/Q+c4LdJ6yTTo/zHX+gPHbix0hk0w1fgJEHs7YYZGnp6mRiaBmAaJ6iT8zcFGmrUhwB+LYaAbCHJYauVpWmrnXKbbi4UXrkJO+K88sU31NGAfYY7YYI+rITSZzUs4gC42mWdMoHlbuKeRlRUhFxF2CtfPkN59pNFHjJRG0cphNxnqCKwcimUk2zktv/kCjXmQBCo3QJMvE1ccX70a+T0JgOle7Cox1LIG5fIHA8IVMkqlcXSbvRl02E3XyQqIuBZMSwpQXoNIxvVKVM3JcOnZKEhkjQQcVm9+XnUxMaA+dnkxq6QnuMJTyk0EhRdEBMfGimRu/nDY373XWkuq9smyNwknIQEb5Z2XAPpYMdDfIQGXvIKS3eDFXNUcFJGZOebvKewsrJn9gudU1tb9NOywPV4Vmw7WpJEMCrd3sKxurpsUXwoHn78dSXfBAPpdf1QNVDMSGOKQ2AT6RCqnlrxcbYmNG+JOzUOY46FxXjoNqGpks0/QqfiKoOqoCql1xlOxDzZGGSrbs/dHTq6HnXuUGzT7y9aIOJBXgMZmBX8ZPKmOOCrbS3Dr/AkYp+uiriyV7IjPtD3ET4br0Srv9Rnf4fyQ1n5tM5/wjTxFj2wmyldGfrFan23sdKNImfD6P4Shhujolkv82UtplLrVv9iWlvSXZe4aUav/JutDMoHvnCacqkoMn8XhQKF3XoFS7hzUfYH0m5L86A/LffJD/efJnB+dryV91dCzy18Z5C/KnglM874sZefNMaH9zBrS3N31B/OB9hUaX9mXrqldi0mWVsbtSf4Ov7DL3Rvm4Xf+qc3YJub3l6nZa7Dype/d7Scn3pmbV0a68fG1K3rXf4lSu38LPOSe3z+FGbn9cyffIyvfmf9XRsfhfG+dN+F+/k59lVm6/79u4qub/DUua5/+w69z9Bw==</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

24
GCryptCLI/idea/notes.md Normal file
View File

@ -0,0 +1,24 @@
* Add a new iobase: bytes.
For cleartext:
Format is ALWAYS raw bytes. That works fine with text, and files.
The iobase ONLY affects ciphertext!
For ciphertext:
format depends..:
If none specified:
- raw bytes if an outputfile is given
- hex if output to stdout
If specified:
Just use the specified iobase. Even if it means dumping bytes to stdout, or writing base-2 to files.
* --intext or --infile should no longer be required. Default behaviour should be reading from stdin.
* No guessing where to output (like file-in got saved to another file beforehand.) Default behaviour should be stdout.
* --progress should output reports to stderr. This way it won't disturb piping the ciphertext to another program.
* Add a module to generate keyfiles.
Should seed a gcrypt prng with std::random_device, and then dump BLOCK_SIZE bits to the specified output.

View File

@ -1,7 +1,7 @@
#ifndef GCRYPTCLI_VERSION_H #ifndef GCRYPTCLI_VERSION_H
#define GCRYPTCLI_VERSION_H #define GCRYPTCLI_VERSION_H
#define GCRYPTCLI_VERSION 0.1251 #define GCRYPTCLI_VERSION 0.12512
#endif #endif

View File

@ -23,15 +23,14 @@ Have these depencies installed:
6) Compile: `make`. 6) Compile: `make`.
The executable `gcrypt` should now lie in `build/`. The executable `gcrypt` should now lie in `build/`.
If you want to use this globally, you could move it to `/usr/bin/`, or some other location in your $PATH. If you want to use this globally, you could move it to `/usr/bin/`, or some other location in your $PATH. ### Options and flags
### Options and flags ### All arguments and flags:
All arguments and flags:
``` ```
CLI for the GCrypt cipher/obfuscator CLI for the GCrypt cipher/obfuscator
Copyright (c) 2022 Leon Etienne Copyright (c) 2022 Leon Etienne
GCrypt v0.236 GCryptLib v0.236
GCrypt CLI v0.1241 GCryptCLI v0.12511
THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT "https://gitea.leonetienne.de/leonetienne/GCrypt" THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT "https://gitea.leonetienne.de/leonetienne/GCrypt"
==== AVAILABLE PARAMETERS ==== ==== AVAILABLE PARAMETERS ====
@ -40,7 +39,11 @@ THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS T
--iobase-16 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base16 (hex) --iobase-16 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base16 (hex)
--progress -p VOID Print digestion progress to stdout. May be advisable for large files, as the cipher is rather slow. --progress-interval INT default=['1000'] Print digestion progress reports every these many data blocks.
--buffer-input VOID Will read the entire input before beginning any digestion.
--progress -p VOID Print digestion progress to stderr. May be advisable for large files, as the cipher is rather slow.
--cli-version -v VOID Will supply the version of GCryptCLI used. --cli-version -v VOID Will supply the version of GCryptCLI used.
@ -50,19 +53,7 @@ THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS T
--iobase-10 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base10 --iobase-10 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base10
--ofile -o STRING incompatibilities=[--ostdout, --hash] Write output in this file. --buffer-output VOID Will digest the entire data before initiating any output.
--key -k STRING incompatibilities=[--keyfile, --keyask, --hash] Use this value as a password to extrapolate the encryption key. WARNING: Arguments may be logged by the system!
--keyask -ka VOID incompatibilities=[--key, --keyfile, --hash] Read the encryption key from stdin.
--no-newline VOID Don't postfix stdout output with a newline
--puffer-output VOID Will digest the entire data before initiating any output.
--puffer-input VOID Will read the entire input before beginning any digestion.
--decrypt -d VOID incompatibilities=[--encrypt, --hash, --generate-key] Use decryption module.
--lib-version VOID Will supply the version of GCryptLib used. --lib-version VOID Will supply the version of GCryptLib used.
@ -80,6 +71,16 @@ THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS T
--generate-key VOID incompatibilities=[--encrypt, --decrypt, --hash] Use the key generation module. Will generate a random key based on hardware events, output it, and exit. --generate-key VOID incompatibilities=[--encrypt, --decrypt, --hash] Use the key generation module. Will generate a random key based on hardware events, output it, and exit.
--ofile -o STRING incompatibilities=[--ostdout, --hash] Write output in this file.
--key -k STRING incompatibilities=[--keyfile, --keyask, --hash] Use this value as a password to extrapolate the encryption key. WARNING: Arguments may be logged by the system!
--keyask -ka VOID incompatibilities=[--key, --keyfile, --hash] Read the encryption key from stdin.
--no-newline VOID Don't postfix stdout output with a newline
--decrypt -d VOID incompatibilities=[--encrypt, --hash, --generate-key] Use decryption module.
--hash -h VOID incompatibilities=[--encrypt, --decrypt, --generate-key] Use the GHash hash module to calculate a hashsum. --hash -h VOID incompatibilities=[--encrypt, --decrypt, --generate-key] Use the GHash hash module to calculate a hashsum.
--intext -it STRING incompatibilities=[--infile] Encrypt this string. --intext -it STRING incompatibilities=[--infile] Encrypt this string.
@ -101,9 +102,8 @@ hello, world!
``` ```
#### What about not using hex? #### What about not using hex?
> :warning: Custom bases are super imperformant. > :warning: Custom bases are super imperformant. Please only use them for text-based input...
> Encrypting all text in main.cpp took about two seconds. > The larger the base, the exponentially longer it takes to recode.
> Outputting it in base-64 took just over ONE MINUTE. In base-2 over SEVEN MINUTES. The general trend seems to be, the larger the base, the better it performs.
```sh ```sh
$ gcrypt -e --keyask --intext "hello, world!" --iobase-2 $ gcrypt -e --keyask --intext "hello, world!" --iobase-2
@ -130,44 +130,34 @@ $ gcrypt -e --key "secretpassword" --intext "hello, world!"
```sh ```sh
$ gcrypt -e --keyfile "dog.jpg" --intext "hello, world!" $ gcrypt -e --keyfile "dog.jpg" --intext "hello, world!"
``` ```
> :warning: Some operating systems will log cli arguments! One might find your keyfile!
#### Creating keyfiles #### Creating keyfiles
```sh ```sh
$ gcrypt --generate-key --ofile "my-keyfile.bin" $ gcrypt --generate-key --ofile "my-keyfile.bin"
``` ```
This will generate a random 512-bit keyfile from hardware events This will generate a random 512-bit keyfile from hardware events and other random sources, if available.
> :warning: Some operating systems will log cli arguments! One might find your keyfile! To see how this randomness gets sourced, see [std::random_device](https://en.cppreference.com/w/cpp/numeric/random/random_device).
#### Encrypting files #### Encrypting files
```sh ```sh
$ gcrypt -e --keyask --infile "cat.jpg" $ gcrypt -e --keyask --infile "cat.jpg" --ofile "cat.jpg.crypt"
``` ```
File `cat.jpg.crypt` will be created. File `cat.jpg.crypt` will be created.
#### Encrypting files to a target file name
```sh
$ gcrypt -e --keyask --infile "cat.jpg" -o "encrypted_cat.jpg"
```
File `encrypted_cat.jpg` will be created.
#### Decrypting files #### Decrypting files
```sh ```sh
$ gcrypt -d --keyask --infile "cat.jpg.crypt" $ gcrypt -d --keyask --infile "cat.jpg.crypt" --ofile "decrypted_cat.jpg"
``` ```
File `cat.jpg.crypt.plain` will be created. Its contents match `cat.jpg` File `decrypted_cat.jpg` will be created. You can now open it again. Its contents match `cat.jpg`.
> :warning: Since this is a block cipher, decrypted files may be tailpadded with a few nullbytes. > :warning: Since this is a block cipher, decrypted files may be tailpadded with a few nullbytes.
#### Decrypting files to a target file name
```sh
$ gcrypt -d --keyask --infile "cat.jpg.crypt" -o "decrypted_cat.jpg"
```
File `decrypted_cat.jpg` will be created. You can now open it again.
#### Encrypting large files takes time. How's the progress? #### Encrypting large files takes time. How's the progress?
```sh ```sh
$ gcrypt -e --keyask --infile "cat.jpg" --progress $ gcrypt -e --keyask --infile "cat.jpg" --buffer-input --progress
``` ```
Something along the lines of `Encrypting... (Block 200 / 1148 - 17.4216%)` will be regularly, but not too often, printed to stdout. Something along the lines of `Encrypting... (Block 200 / 1148 - 17.4216%)` will be regularly, but not too often, printed to stderr.
Obviously, to print progress, we have to know the size of the input. Hence, it has to be buffered.
#### Any cipher can also compute hashsums #### Any cipher can also compute hashsums
```sh ```sh
@ -177,15 +167,16 @@ a96f42c9d97e46b9e1ed7de5182770170d4ef9b7b8264f3fbd89b38dc60c1fe06232653f58560133
$ gcrypt -h --infile "cat.jpg" $ gcrypt -h --infile "cat.jpg"
fe6bdfb6ec39771c4fdcdc40e52397bcd67fbfef0ad5a15ebbd8b9e4c2a815848b3984eda5ef6f727e9e420c23500c90c42ab80ac5659048be8969357741e3e5 fe6bdfb6ec39771c4fdcdc40e52397bcd67fbfef0ad5a15ebbd8b9e4c2a815848b3984eda5ef6f727e9e420c23500c90c42ab80ac5659048be8969357741e3e5
``` ```
The hashsum will always be of size BLOCK_SIZE. That is 512. The hashsum will always be of size BLOCK_SIZE. That is 512 bits.
#### What version am i running? #### What version am i running?
Depending on wether you want to know the GCrypt version or the CLI's version, Depending on whether you want to know the GCryptLib version or the CLI's version,
use either `--cli-version` or `--lib-version`. use either `--cli-version` or `--lib-version`.
It will print out a floating point number. It will print out a floating point number.
You can see both in the `--help`-page.
#### I want to stream the output of file en/decryption. #### Streaming the output of file en/decryption.
// Easily! If you do not supply any output or input, stdout and stdin will be used instead! Easily! If you do not supply any output or input, stdout and stdin will be used instead!
```sh ```sh
# mpv is a media player, as an example # mpv is a media player, as an example
$ gcrypt -d --key "123" --infile "music.mp3.crypt" | mpv - $ gcrypt -d --key "123" --infile "music.mp3.crypt" | mpv -
@ -195,8 +186,8 @@ $ gcrypt -d --key "123" --infile "music.mp3.crypt" | mpv -
By default, gcrypt will read a block, digest it, and output the result immediately. By default, gcrypt will read a block, digest it, and output the result immediately.
Sometimes you don't want that. Use these flags, respectively: Sometimes you don't want that. Use these flags, respectively:
``` ```
--puffer-input # Reads all input to memory before beginning to digest it --buffer-input # Reads all input to memory before beginning to digest it
--puffer-output # Digests all input before beginning to write any --buffer-output # Digests all input before beginning to write any
``` ```
## Esoteric data formats ## Esoteric data formats
@ -212,6 +203,14 @@ $ gcrypt -e --keyask --intext "hello, world!" --iobase-ugh
Grr... Wha-? Aah! Aah! Uh-huh... Aah! Grr... Aah! Aah! Uh-huh... Ah... Ugh Grr... Ugh Pft! Nu-uh... Gah! Bah! Huh...? Ah... Uh-huh... Wha-? Pft! Nu-uh... Ugh Wha-? Psh! Agh! Ah... Aah! Nu-uh... Psh! Pft! Nu-uh... Psh! Shh! Gah! Ah... Pft! Gah! Shh! Bah! Gah! Uh-huh... Gah! Duh! Aah! Uh-huh... Er- Nu-uh... Gah! Wha-? Pft! Er- Shh! Ah... Huh...? Er- Wha-? Uh-huh... Ah... Shh! Ugh Bah! Wha-? Uaah! Ah... Nu-uh... Uh-huh... Ugh Pft! Pft! Gah! Shh! Shh! Wha-? Bah! Ugh Grr... Aah! Pft! Nu-uh... Ah... Aah! Agh! Er- Psh! Uaah! Nu-uh... Ugh Wha-? Uh-huh... Shh! Pft! Aah! Agh! Grr... Agh! Agh! Grr... Pft! Wha-? Wha-? Uh-huh... Aah! Ugh Aah! Pft! Gah! Bah! Huh...? Ugh Bah! Uaah! Gah! Bah! Duh! Duh! Uh-huh... Grr... Ah... Grr... Ugh Ah... Pft! Grr... Wha-? Aah! Aah! Uh-huh... Aah! Grr... Aah! Aah! Uh-huh... Ah... Ugh Grr... Ugh Pft! Nu-uh... Gah! Bah! Huh...? Ah... Uh-huh... Wha-? Pft! Nu-uh... Ugh Wha-? Psh! Agh! Ah... Aah! Nu-uh... Psh! Pft! Nu-uh... Psh! Shh! Gah! Ah... Pft! Gah! Shh! Bah! Gah! Uh-huh... Gah! Duh! Aah! Uh-huh... Er- Nu-uh... Gah! Wha-? Pft! Er- Shh! Ah... Huh...? Er- Wha-? Uh-huh... Ah... Shh! Ugh Bah! Wha-? Uaah! Ah... Nu-uh... Uh-huh... Ugh Pft! Pft! Gah! Shh! Shh! Wha-? Bah! Ugh Grr... Aah! Pft! Nu-uh... Ah... Aah! Agh! Er- Psh! Uaah! Nu-uh... Ugh Wha-? Uh-huh... Shh! Pft! Aah! Agh! Grr... Agh! Agh! Grr... Pft! Wha-? Wha-? Uh-huh... Aah! Ugh Aah! Pft! Gah! Bah! Huh...? Ugh Bah! Uaah! Gah! Bah! Duh! Duh! Uh-huh... Grr... Ah... Grr... Ugh Ah... Pft!
``` ```
Yes, you can send these... *adventorous* texsts to your friends, and they can actually decipher them
back to the original message :). Almost going a bit into the steganography territory here, hehe.
These weird number bases don't impact security at all. This is because they are just that.
Number bases, to represent a bunch of bytes, that is our ciphertext.
These just bring a bit more fun into the big world of cryptography :).
## LICENSE ## LICENSE
``` ```
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE

View File

@ -13,8 +13,8 @@ void CommandlineInterface::Init(int argc, const char* const* argv) {
std::stringstream ss; std::stringstream ss;
ss << "CLI for the GCrypt cipher/obfuscator" << std::endl ss << "CLI for the GCrypt cipher/obfuscator" << std::endl
<< "Copyright (c) 2022 Leon Etienne" << std::endl << "Copyright (c) 2022 Leon Etienne" << std::endl
<< "GCrypt v" << GCRYPT_VERSION << std::endl << "GCryptLib v" << GCRYPT_VERSION << std::endl
<< "GCrypt CLI v" << GCRYPTCLI_VERSION << std::endl << "GCryptCLI v" << GCRYPTCLI_VERSION << std::endl
<< "THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT \"https://gitea.leonetienne.de/leonetienne/GCrypt\""; << "THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT \"https://gitea.leonetienne.de/leonetienne/GCrypt\"";
nupp.SetBriefDescription(ss.str()); nupp.SetBriefDescription(ss.str());
ss.str(""); ss.str("");
@ -102,11 +102,11 @@ void CommandlineInterface::Init(int argc, const char* const* argv) {
nupp.RegisterConstraint("--cli-version", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {})); nupp.RegisterConstraint("--cli-version", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
nupp.RegisterAbbreviation("-v", "--cli-version"); nupp.RegisterAbbreviation("-v", "--cli-version");
nupp.RegisterDescription("--puffer-input", "Will read the entire input before beginning any digestion."); nupp.RegisterDescription("--buffer-input", "Will read the entire input before beginning any digestion.");
nupp.RegisterConstraint("--puffer-input", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {})); nupp.RegisterConstraint("--buffer-input", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
nupp.RegisterDescription("--puffer-output", "Will digest the entire data before initiating any output."); nupp.RegisterDescription("--buffer-output", "Will digest the entire data before initiating any output.");
nupp.RegisterConstraint("--puffer-output", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {})); nupp.RegisterConstraint("--buffer-output", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
nupp.RegisterDescription("--no-newline", "Don't postfix stdout output with a newline"); nupp.RegisterDescription("--no-newline", "Don't postfix stdout output with a newline");
nupp.RegisterConstraint("--no-newline", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {})); nupp.RegisterConstraint("--no-newline", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
@ -173,10 +173,10 @@ void CommandlineInterface::SpecialCompatibilityChecking() {
if ( if (
(nupp.HasParam("--progress")) && (nupp.HasParam("--progress")) &&
(!nupp.HasParam("--puffer-input")) (!nupp.HasParam("--buffer-input"))
) { ) {
CrashWithMsg("--progress requires --puffer-input to work!"); CrashWithMsg("--progress requires --buffer-input to work!");
} }
return; return;

View File

@ -57,9 +57,7 @@ void DataIngestionLayer::Init() {
} }
// Derive from our the current module if we're reading ciphertext or not // Derive from our the current module if we're reading ciphertext or not
if ( if (Configuration::activeModule == Configuration::MODULE::DECRYPTION) {
(Configuration::activeModule == Configuration::MODULE::DECRYPTION)
) {
isReadingCiphertext = true; isReadingCiphertext = true;
} }
else { else {
@ -325,16 +323,16 @@ bool DataIngestionLayer::ReachedEOF() {
} }
bool DataIngestionLayer::IsBlockReady() { bool DataIngestionLayer::IsBlockReady() {
// We're not ready, if we haven't reached EOF, if we should puffer // We're not ready, if we haven't reached EOF, if we should buffer
// the input. // the input.
if ( if (
(CommandlineInterface::Get().HasParam("--puffer-input")) && (CommandlineInterface::Get().HasParam("--buffer-input")) &&
(!reachedEof) (!reachedEof)
) { ) {
return false; return false;
} }
// If we're not puffering, just return whether or not // If we're not buffering, just return whether or not
// we have any blocks... // we have any blocks...
return blocks.size() > 0; return blocks.size() > 0;
} }

View File

@ -65,13 +65,13 @@ void DataOutputLayer::WriteBlock() {
} }
// Check if we have any block to write // Check if we have any block to write
// and if we should (output-puffering) // and if we should (output-buffering)
// Basically: only output if we have anything to output, and // Basically: only output if we have anything to output, and
// if --puffer-output is given, only output once we have reachedEof. // if --buffer-output is given, only output once we have reachedEof.
if ( if (
(blocks.size() > 0) && (blocks.size() > 0) &&
( (
(!CommandlineInterface::Get().HasParam("--puffer-output")) || (!CommandlineInterface::Get().HasParam("--buffer-output")) ||
(reachedEof) (reachedEof)
) )
) { ) {

View File

@ -1,6 +1,6 @@
all: all:
# Copy all but the header of the readme here # Copy all but the header of the readme here
tail ../../readme.md -n +2 > index.md tail ../../readme.md -n +9 > index.md
# #
# Run doxygen # Run doxygen
doxygen doxyfig doxygen doxyfig

View File

@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places. # title of most generated pages and in a few other places.
# The default value is: My Project. # The default value is: My Project.
PROJECT_NAME = "Leonetienne/GhettoCrypt" PROJECT_NAME = "Leonetienne/GCrypt"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version

View File

@ -4,7 +4,7 @@
#include <cstdint> #include <cstdint>
#include <array> #include <array>
#include <string> #include <string>
#include <ostream> #include <iosfwd>
#include <bitset> #include <bitset>
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {

View File

@ -9,7 +9,11 @@
// Just to be sure, the compiler will optimize this // Just to be sure, the compiler will optimize this
// little formula out, let's do it in the preprocessor // little formula out, let's do it in the preprocessor
#define MAT_INDEX(row, column) (column*4 + row) namespace {
constexpr std::size_t MAT_INDEX(const std::size_t row, const std::size_t column) {
return column*4 + row;
}
}
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
@ -148,25 +152,25 @@ namespace Leonetienne::GCrypt {
// Maybe pre-calculate the 1d-index...? // Maybe pre-calculate the 1d-index...?
m.Get(0, 0) = (this->Get(0, 0) * o.Get(0, 0)) + (this->Get(0, 1) * o.Get(1, 0)) + (this->Get(0, 2) * o.Get(2, 0)) + (this->Get(0, 3) * o.Get(3, 0)); m.Get(MAT_INDEX(0, 0)) = (this->Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 0))) + (this->Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 0))) + (this->Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 0))) + (this->Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 0)));
m.Get(0, 1) = (this->Get(0, 0) * o.Get(0, 1)) + (this->Get(0, 1) * o.Get(1, 1)) + (this->Get(0, 2) * o.Get(2, 1)) + (this->Get(0, 3) * o.Get(3, 1)); m.Get(MAT_INDEX(0, 1)) = (this->Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 1))) + (this->Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 1))) + (this->Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 1))) + (this->Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 1)));
m.Get(0, 2) = (this->Get(0, 0) * o.Get(0, 2)) + (this->Get(0, 1) * o.Get(1, 2)) + (this->Get(0, 2) * o.Get(2, 2)) + (this->Get(0, 3) * o.Get(3, 2)); m.Get(MAT_INDEX(0, 2)) = (this->Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 2))) + (this->Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 2))) + (this->Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 2))) + (this->Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 2)));
m.Get(0, 3) = (this->Get(0, 0) * o.Get(0, 3)) + (this->Get(0, 1) * o.Get(1, 3)) + (this->Get(0, 2) * o.Get(2, 3)) + (this->Get(0, 3) * o.Get(3, 3)); m.Get(MAT_INDEX(0, 3)) = (this->Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 3))) + (this->Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 3))) + (this->Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 3))) + (this->Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 3)));
m.Get(1, 0) = (this->Get(1, 0) * o.Get(0, 0)) + (this->Get(1, 1) * o.Get(1, 0)) + (this->Get(1, 2) * o.Get(2, 0)) + (this->Get(1, 3) * o.Get(3, 0)); m.Get(MAT_INDEX(1, 0)) = (this->Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 0))) + (this->Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 0))) + (this->Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 0))) + (this->Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 0)));
m.Get(1, 1) = (this->Get(1, 0) * o.Get(0, 1)) + (this->Get(1, 1) * o.Get(1, 1)) + (this->Get(1, 2) * o.Get(2, 1)) + (this->Get(1, 3) * o.Get(3, 1)); m.Get(MAT_INDEX(1, 1)) = (this->Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 1))) + (this->Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 1))) + (this->Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 1))) + (this->Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 1)));
m.Get(1, 2) = (this->Get(1, 0) * o.Get(0, 2)) + (this->Get(1, 1) * o.Get(1, 2)) + (this->Get(1, 2) * o.Get(2, 2)) + (this->Get(1, 3) * o.Get(3, 2)); m.Get(MAT_INDEX(1, 2)) = (this->Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 2))) + (this->Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 2))) + (this->Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 2))) + (this->Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 2)));
m.Get(1, 3) = (this->Get(1, 0) * o.Get(0, 3)) + (this->Get(1, 1) * o.Get(1, 3)) + (this->Get(1, 2) * o.Get(2, 3)) + (this->Get(1, 3) * o.Get(3, 3)); m.Get(MAT_INDEX(1, 3)) = (this->Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 3))) + (this->Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 3))) + (this->Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 3))) + (this->Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 3)));
m.Get(2, 0) = (this->Get(2, 0) * o.Get(0, 0)) + (this->Get(2, 1) * o.Get(1, 0)) + (this->Get(2, 2) * o.Get(2, 0)) + (this->Get(2, 3) * o.Get(3, 0)); m.Get(MAT_INDEX(2, 0)) = (this->Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 0))) + (this->Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 0))) + (this->Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 0))) + (this->Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 0)));
m.Get(2, 1) = (this->Get(2, 0) * o.Get(0, 1)) + (this->Get(2, 1) * o.Get(1, 1)) + (this->Get(2, 2) * o.Get(2, 1)) + (this->Get(2, 3) * o.Get(3, 1)); m.Get(MAT_INDEX(2, 1)) = (this->Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 1))) + (this->Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 1))) + (this->Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 1))) + (this->Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 1)));
m.Get(2, 2) = (this->Get(2, 0) * o.Get(0, 2)) + (this->Get(2, 1) * o.Get(1, 2)) + (this->Get(2, 2) * o.Get(2, 2)) + (this->Get(2, 3) * o.Get(3, 2)); m.Get(MAT_INDEX(2, 2)) = (this->Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 2))) + (this->Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 2))) + (this->Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 2))) + (this->Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 2)));
m.Get(2, 3) = (this->Get(2, 0) * o.Get(0, 3)) + (this->Get(2, 1) * o.Get(1, 3)) + (this->Get(2, 2) * o.Get(2, 3)) + (this->Get(2, 3) * o.Get(3, 3)); m.Get(MAT_INDEX(2, 3)) = (this->Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 3))) + (this->Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 3))) + (this->Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 3))) + (this->Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 3)));
m.Get(3, 0) = (this->Get(3, 0) * o.Get(0, 0)) + (this->Get(3, 1) * o.Get(1, 0)) + (this->Get(3, 2) * o.Get(2, 0)) + (this->Get(3, 3) * o.Get(3, 0)); m.Get(MAT_INDEX(3, 0)) = (this->Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 0))) + (this->Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 0))) + (this->Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 0))) + (this->Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 0)));
m.Get(3, 1) = (this->Get(3, 0) * o.Get(0, 1)) + (this->Get(3, 1) * o.Get(1, 1)) + (this->Get(3, 2) * o.Get(2, 1)) + (this->Get(3, 3) * o.Get(3, 1)); m.Get(MAT_INDEX(3, 1)) = (this->Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 1))) + (this->Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 1))) + (this->Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 1))) + (this->Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 1)));
m.Get(3, 2) = (this->Get(3, 0) * o.Get(0, 2)) + (this->Get(3, 1) * o.Get(1, 2)) + (this->Get(3, 2) * o.Get(2, 2)) + (this->Get(3, 3) * o.Get(3, 2)); m.Get(MAT_INDEX(3, 2)) = (this->Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 2))) + (this->Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 2))) + (this->Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 2))) + (this->Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 2)));
m.Get(3, 3) = (this->Get(3, 0) * o.Get(0, 3)) + (this->Get(3, 1) * o.Get(1, 3)) + (this->Get(3, 2) * o.Get(2, 3)) + (this->Get(3, 3) * o.Get(3, 3)); m.Get(MAT_INDEX(3, 3)) = (this->Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 3))) + (this->Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 3))) + (this->Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 3))) + (this->Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 3)));
return m; return m;
} }
@ -183,25 +187,25 @@ namespace Leonetienne::GCrypt {
// Maybe pre-calculate the 1d-index...? // Maybe pre-calculate the 1d-index...?
this->Get(0, 0) = (m.Get(0, 0) * o.Get(0, 0)) + (m.Get(0, 1) * o.Get(1, 0)) + (m.Get(0, 2) * o.Get(2, 0)) + (m.Get(0, 3) * o.Get(3, 0)); this->Get(MAT_INDEX(0, 0)) = (m.Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 0))) + (m.Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 0))) + (m.Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 0))) + (m.Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 0)));
this->Get(0, 1) = (m.Get(0, 0) * o.Get(0, 1)) + (m.Get(0, 1) * o.Get(1, 1)) + (m.Get(0, 2) * o.Get(2, 1)) + (m.Get(0, 3) * o.Get(3, 1)); this->Get(MAT_INDEX(0, 1)) = (m.Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 1))) + (m.Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 1))) + (m.Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 1))) + (m.Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 1)));
this->Get(0, 2) = (m.Get(0, 0) * o.Get(0, 2)) + (m.Get(0, 1) * o.Get(1, 2)) + (m.Get(0, 2) * o.Get(2, 2)) + (m.Get(0, 3) * o.Get(3, 2)); this->Get(MAT_INDEX(0, 2)) = (m.Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 2))) + (m.Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 2))) + (m.Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 2))) + (m.Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 2)));
this->Get(0, 3) = (m.Get(0, 0) * o.Get(0, 3)) + (m.Get(0, 1) * o.Get(1, 3)) + (m.Get(0, 2) * o.Get(2, 3)) + (m.Get(0, 3) * o.Get(3, 3)); this->Get(MAT_INDEX(0, 3)) = (m.Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 3))) + (m.Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 3))) + (m.Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 3))) + (m.Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 3)));
this->Get(1, 0) = (m.Get(1, 0) * o.Get(0, 0)) + (m.Get(1, 1) * o.Get(1, 0)) + (m.Get(1, 2) * o.Get(2, 0)) + (m.Get(1, 3) * o.Get(3, 0)); this->Get(MAT_INDEX(1, 0)) = (m.Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 0))) + (m.Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 0))) + (m.Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 0))) + (m.Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 0)));
this->Get(1, 1) = (m.Get(1, 0) * o.Get(0, 1)) + (m.Get(1, 1) * o.Get(1, 1)) + (m.Get(1, 2) * o.Get(2, 1)) + (m.Get(1, 3) * o.Get(3, 1)); this->Get(MAT_INDEX(1, 1)) = (m.Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 1))) + (m.Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 1))) + (m.Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 1))) + (m.Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 1)));
this->Get(1, 2) = (m.Get(1, 0) * o.Get(0, 2)) + (m.Get(1, 1) * o.Get(1, 2)) + (m.Get(1, 2) * o.Get(2, 2)) + (m.Get(1, 3) * o.Get(3, 2)); this->Get(MAT_INDEX(1, 2)) = (m.Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 2))) + (m.Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 2))) + (m.Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 2))) + (m.Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 2)));
this->Get(1, 3) = (m.Get(1, 0) * o.Get(0, 3)) + (m.Get(1, 1) * o.Get(1, 3)) + (m.Get(1, 2) * o.Get(2, 3)) + (m.Get(1, 3) * o.Get(3, 3)); this->Get(MAT_INDEX(1, 3)) = (m.Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 3))) + (m.Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 3))) + (m.Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 3))) + (m.Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 3)));
this->Get(2, 0) = (m.Get(2, 0) * o.Get(0, 0)) + (m.Get(2, 1) * o.Get(1, 0)) + (m.Get(2, 2) * o.Get(2, 0)) + (m.Get(2, 3) * o.Get(3, 0)); this->Get(MAT_INDEX(2, 0)) = (m.Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 0))) + (m.Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 0))) + (m.Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 0))) + (m.Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 0)));
this->Get(2, 1) = (m.Get(2, 0) * o.Get(0, 1)) + (m.Get(2, 1) * o.Get(1, 1)) + (m.Get(2, 2) * o.Get(2, 1)) + (m.Get(2, 3) * o.Get(3, 1)); this->Get(MAT_INDEX(2, 1)) = (m.Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 1))) + (m.Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 1))) + (m.Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 1))) + (m.Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 1)));
this->Get(2, 2) = (m.Get(2, 0) * o.Get(0, 2)) + (m.Get(2, 1) * o.Get(1, 2)) + (m.Get(2, 2) * o.Get(2, 2)) + (m.Get(2, 3) * o.Get(3, 2)); this->Get(MAT_INDEX(2, 2)) = (m.Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 2))) + (m.Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 2))) + (m.Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 2))) + (m.Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 2)));
this->Get(2, 3) = (m.Get(2, 0) * o.Get(0, 3)) + (m.Get(2, 1) * o.Get(1, 3)) + (m.Get(2, 2) * o.Get(2, 3)) + (m.Get(2, 3) * o.Get(3, 3)); this->Get(MAT_INDEX(2, 3)) = (m.Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 3))) + (m.Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 3))) + (m.Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 3))) + (m.Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 3)));
this->Get(3, 0) = (m.Get(3, 0) * o.Get(0, 0)) + (m.Get(3, 1) * o.Get(1, 0)) + (m.Get(3, 2) * o.Get(2, 0)) + (m.Get(3, 3) * o.Get(3, 0)); this->Get(MAT_INDEX(3, 0)) = (m.Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 0))) + (m.Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 0))) + (m.Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 0))) + (m.Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 0)));
this->Get(3, 1) = (m.Get(3, 0) * o.Get(0, 1)) + (m.Get(3, 1) * o.Get(1, 1)) + (m.Get(3, 2) * o.Get(2, 1)) + (m.Get(3, 3) * o.Get(3, 1)); this->Get(MAT_INDEX(3, 1)) = (m.Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 1))) + (m.Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 1))) + (m.Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 1))) + (m.Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 1)));
this->Get(3, 2) = (m.Get(3, 0) * o.Get(0, 2)) + (m.Get(3, 1) * o.Get(1, 2)) + (m.Get(3, 2) * o.Get(2, 2)) + (m.Get(3, 3) * o.Get(3, 2)); this->Get(MAT_INDEX(3, 2)) = (m.Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 2))) + (m.Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 2))) + (m.Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 2))) + (m.Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 2)));
this->Get(3, 3) = (m.Get(3, 0) * o.Get(0, 3)) + (m.Get(3, 1) * o.Get(1, 3)) + (m.Get(3, 2) * o.Get(2, 3)) + (m.Get(3, 3) * o.Get(3, 3)); this->Get(MAT_INDEX(3, 3)) = (m.Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 3))) + (m.Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 3))) + (m.Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 3))) + (m.Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 3)));
return; return;
} }
@ -833,6 +837,3 @@ namespace Leonetienne::GCrypt {
template class Basic_Block<std::uint16_t>; template class Basic_Block<std::uint16_t>;
} }
#undef MAT_INDEX

View File

@ -302,8 +302,8 @@ TEST_CASE(__FILE__"/operator-&=", "[Block]") {
// Tests that subtraction undoes addition, and vica versa // Tests that subtraction undoes addition, and vica versa
TEST_CASE(__FILE__"/subtraction-undoes-addition", "[Block]") { TEST_CASE(__FILE__"/subtraction-undoes-addition", "[Block]") {
// Setup // Setup
const Block a = Key::FromPassword("Halleluja"); const Block a = Key::Random();
const Block b = Key::FromPassword("Ananas"); const Block b = Key::Random();
// Exercise // Exercise
const Block a_plus_b = a + b; const Block a_plus_b = a + b;
@ -441,7 +441,7 @@ TEST_CASE(__FILE__"/shift-rows-up", "[Block]") {
// Tests that ShiftRowsUpInplace() does the exact same thing as ShiftRowsUp() // Tests that ShiftRowsUpInplace() does the exact same thing as ShiftRowsUp()
TEST_CASE(__FILE__"/shift-rows-up-same-as-inplace", "[Block]") { TEST_CASE(__FILE__"/shift-rows-up-same-as-inplace", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise and verify // Exercise and verify
@ -475,7 +475,7 @@ TEST_CASE(__FILE__"/shift-rows-down", "[Block]") {
// Tests that ShiftRowsDownInplace() does the exact same thing as ShiftRowsDown() // Tests that ShiftRowsDownInplace() does the exact same thing as ShiftRowsDown()
TEST_CASE(__FILE__"/shift-rows-down-same-as-inplace", "[Block]") { TEST_CASE(__FILE__"/shift-rows-down-same-as-inplace", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise and verify // Exercise and verify
@ -509,7 +509,7 @@ TEST_CASE(__FILE__"/shift-columns-left", "[Block]") {
// Tests that ShiftColumnsLeftInplace()() does the exact same thing as ShiftColumnsLeft() // Tests that ShiftColumnsLeftInplace()() does the exact same thing as ShiftColumnsLeft()
TEST_CASE(__FILE__"/shift-columns-left-same-as-inplace", "[Block]") { TEST_CASE(__FILE__"/shift-columns-left-same-as-inplace", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise and verify // Exercise and verify
@ -543,7 +543,7 @@ TEST_CASE(__FILE__"/shift-columns-right", "[Block]") {
// Tests that ShiftColumnsRightInplace()() does the exact same thing as ShiftColumnsRight() // Tests that ShiftColumnsRightInplace()() does the exact same thing as ShiftColumnsRight()
TEST_CASE(__FILE__"/shift-columns-right-same-as-inplace", "[Block]") { TEST_CASE(__FILE__"/shift-columns-right-same-as-inplace", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise and verify // Exercise and verify
@ -576,7 +576,7 @@ TEST_CASE(__FILE__"/shift-cells-left", "[Block]") {
// Tests that ShiftCellsLeftInplace()() does the exact same thing as ShiftCellsLeft() // Tests that ShiftCellsLeftInplace()() does the exact same thing as ShiftCellsLeft()
TEST_CASE(__FILE__"/shift-cells-left-same-as-inplace", "[Block]") { TEST_CASE(__FILE__"/shift-cells-left-same-as-inplace", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise and verify // Exercise and verify
@ -609,7 +609,7 @@ TEST_CASE(__FILE__"/shift-cells-right", "[Block]") {
// Tests that ShiftCellsRightInplace()() does the exact same thing as ShiftCellsRight() // Tests that ShiftCellsRightInplace()() does the exact same thing as ShiftCellsRight()
TEST_CASE(__FILE__"/shift-cells-right-same-as-inplace", "[Block]") { TEST_CASE(__FILE__"/shift-cells-right-same-as-inplace", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise and verify // Exercise and verify
@ -620,7 +620,7 @@ TEST_CASE(__FILE__"/shift-cells-right-same-as-inplace", "[Block]") {
// Tests that shifting down undoes shifting up, and vica versa // Tests that shifting down undoes shifting up, and vica versa
TEST_CASE(__FILE__"/shift-down-undoes-shift-up", "[Block]") { TEST_CASE(__FILE__"/shift-down-undoes-shift-up", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise // Exercise
@ -634,7 +634,7 @@ TEST_CASE(__FILE__"/shift-down-undoes-shift-up", "[Block]") {
// Tests that shifting left undoes shifting right, and vica versa // Tests that shifting left undoes shifting right, and vica versa
TEST_CASE(__FILE__"/shift-left-undoes-shift-right", "[Block]") { TEST_CASE(__FILE__"/shift-left-undoes-shift-right", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise // Exercise
@ -648,7 +648,7 @@ TEST_CASE(__FILE__"/shift-left-undoes-shift-right", "[Block]") {
// Tests that shifting cells left undoes shifting cells right, and vica versa // Tests that shifting cells left undoes shifting cells right, and vica versa
TEST_CASE(__FILE__"/cellshift-left-undoes-cellshift-right", "[Block]") { TEST_CASE(__FILE__"/cellshift-left-undoes-cellshift-right", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;
// Exercise // Exercise
@ -662,7 +662,7 @@ TEST_CASE(__FILE__"/cellshift-left-undoes-cellshift-right", "[Block]") {
// Tests that multiple, combined shifts and additions can be undone // Tests that multiple, combined shifts and additions can be undone
TEST_CASE(__FILE__"/multiple-combined-shifts-and-additions-can-be-undone", "[Block]") { TEST_CASE(__FILE__"/multiple-combined-shifts-and-additions-can-be-undone", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
Block key = Key::FromPassword("Papaya"); Block key = Key::FromPassword("Papaya");
const Block initial_a = a; const Block initial_a = a;
@ -689,23 +689,42 @@ TEST_CASE(__FILE__"/multiple-combined-shifts-and-additions-can-be-undone", "[Blo
// Tests that the get-bit method works // Tests that the get-bit method works
TEST_CASE(__FILE__"/get-bit", "[Block]") { TEST_CASE(__FILE__"/get-bit", "[Block]") {
// Setup for (std::size_t i = 0; i < 100; i++) {
Block a = Key::FromPassword("Halleluja"); // Setup
Block a = Key::Random();
// Exercise // Exercise
std::stringstream ss; std::stringstream ss;
for (std::size_t i = 0; i < 512; i++) { for (std::size_t i = 0; i < 512; i++) {
ss << a.GetBit(i); ss << a.GetBit(i);
}
// Verify
REQUIRE(ss.str() == a.ToBinaryString());
} }
}
// Verify // Tests that the set-bit method works
REQUIRE(ss.str() == a.ToBinaryString()); TEST_CASE(__FILE__"/set-bit", "[Block]") {
for (std::size_t i = 0; i < 100; i++) {
// Setup
const std::string a_bits = Key::Random().ToBinaryString();
// Exercise
Block a;
for (std::size_t i = 0; i < 512; i++) {
a.SetBit(i, a_bits[i] == '1');
}
// Verify
REQUIRE(a_bits == a.ToBinaryString());
}
} }
// Tests that the set-bit to-false method works // Tests that the set-bit to-false method works
TEST_CASE(__FILE__"/set-bit-to-false", "[Block]") { TEST_CASE(__FILE__"/set-bit-to-false", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
// Exercise // Exercise
a.SetBit(5, 0); a.SetBit(5, 0);
@ -723,7 +742,7 @@ TEST_CASE(__FILE__"/set-bit-to-false", "[Block]") {
// Tests that the set-bit to-true method works // Tests that the set-bit to-true method works
TEST_CASE(__FILE__"/set-bit-to-true", "[Block]") { TEST_CASE(__FILE__"/set-bit-to-true", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
// Exercise // Exercise
a.SetBit(5, 1); a.SetBit(5, 1);
@ -741,7 +760,7 @@ TEST_CASE(__FILE__"/set-bit-to-true", "[Block]") {
// Tests that the flip-bit method works // Tests that the flip-bit method works
TEST_CASE(__FILE__"/flip-bit", "[Block]") { TEST_CASE(__FILE__"/flip-bit", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
std::string compare = a.ToBinaryString(); std::string compare = a.ToBinaryString();
compare[5] = compare[5] == '1' ? '0' : '1'; compare[5] = compare[5] == '1' ? '0' : '1';
@ -863,7 +882,7 @@ TEST_CASE(__FILE__"/bitshift-right-inplace", "[Block]") {
TEST_CASE(__FILE__"/bitshifting-undoes-itself", "[Block]") { TEST_CASE(__FILE__"/bitshifting-undoes-itself", "[Block]") {
// Setup // Setup
Block a = Key::FromPassword("Halleluja"); Block a = Key::Random();
const Block initial_a = a; const Block initial_a = a;

View File

@ -1,7 +1,12 @@
# GCrypt [![Build Status](https://drone.leonetienne.de/api/badges/leonetienne/GCrypt/status.svg)](https://drone.leonetienne.de/leonetienne/GCrypt)
# GCrypt
*(GhettoCrypt), because frankly I have no idea what the fuck I'm doing* *(GhettoCrypt), because frankly I have no idea what the fuck I'm doing*
<sub>*Please don't use this for anything critical*</sub> <sub>*Please don't use this for anything critical*</sub>
## [Documentation](https://gcrypt.rtfm.leonetienne.de/)
## What the hell is this? ## What the hell is this?
An educational project on implementing a block cipher using a feistel network. An educational project on implementing a block cipher using a feistel network.
This block cipher employs a few modes of operation. Read more about them [here](#modes-of-operation). This block cipher employs a few modes of operation. Read more about them [here](#modes-of-operation).
@ -9,15 +14,15 @@ This block cipher employs a few modes of operation. Read more about them [here](
## Features ## Features
* It has very easy syntax * It has very easy syntax
* It's slow * It's slow
* It absolutely tanks your ram when working with files
* Even leaves some key fragments in there✨
* It's probably super insecure * It's probably super insecure
* But the syntax is pythonlike easy🙇 * But the syntax is pythonlike easy🙇
* 512-bit keys
It's pretty ghetto, you know? It's pretty ghetto, you know?
## What are the actual advantages? ## What are the actual advantages?
* It's two files to import into your project * It's two files to import into your project
* No dependencies
* 1 Line to use * 1 Line to use
* 100% cross plattform * 100% cross plattform
@ -27,7 +32,7 @@ It's pretty ghetto, you know?
### I am not kidding, don't use this for critical stuff! Homebrew ciphers tend to be shit! ### I am not kidding, don't use this for critical stuff! Homebrew ciphers tend to be shit!
Especially mine!🗡️ Especially mine!🗡️
Even assumed it's a good cipher, it's implementation leaves a lot to be desired in terms of being cryptographically secure. The whole leaving partial keys in ram- thingy... Even assumed it's a good cipher, it's implementation leaves a lot to be desired in terms of being cryptographically secure.
## How do I use this? ## How do I use this?
### *"I don't care about the library. Just let me use it from the command line!"* ### *"I don't care about the library. Just let me use it from the command line!"*
@ -102,6 +107,8 @@ This way you can cipher on bitlevel. Examples on how to do this are in [GWrapper
This way you could, for example, decrypt an ecrypted file directly into memory. This way you could, for example, decrypt an ecrypted file directly into memory.
Without saying, this is more advanced and not as-easy as the methods supplied in the wrapper. Without saying, this is more advanced and not as-easy as the methods supplied in the wrapper.
Want more documentation? See the [doxygen page](https://gcrypt.rtfm.leonetienne.de/).
--- ---
## The deets 🍝 ## The deets 🍝
@ -110,25 +117,26 @@ Without saying, this is more advanced and not as-easy as the methods supplied in
* [CBC] This block cipher makes use of cipher block chaining. Nothing special. * [CBC] This block cipher makes use of cipher block chaining. Nothing special.
* [IV] The initialization vector is indeed a bit of special sauce, as it depends on your key instead of being static. It is generated by running the feistel network on *E(m=seed, k=seed)*, which is a one-way function, because *m=k*. * [IV] The initialization vector is indeed a bit of special sauce, as it depends on your key instead of being static. It is generated by running the feistel network on *E(m=seed, k=seed)*, which is a one-way function, because *m=k*.
* [RRKM] Never heard of a mode like this, so i've named it **R**olling**R**ound**K**ey**M**ode. This basically means that the round key extrapolation is carried out continously over EVERY round on EVERY block. So in addition to *M<sub>i</sub>* being dependent on *E(M<sub>i-1</sub>,K<sub>i-1,0</sub>)* due to CBC, so is now *K<sub>i</sub>* dependent on *K<sub>i-1,r</sub>* with *r* being the maximum number of extrapolated keys within a call of *E()*. This is handled within the feistel network class, as an instance lifecycle sees all blocks. Just in case you want to take a peek. * [RRKM] Never heard of a mode like this, so i've named it **R**olling**R**ound**K**ey**M**ode. This basically means that the round key extrapolation is carried out continously over EVERY round on EVERY block. So in addition to *M<sub>i</sub>* being dependent on *E(M<sub>i-1</sub>,K<sub>i-1,0</sub>)* due to CBC, so is now *K<sub>i</sub>* dependent on *K<sub>i-1,r</sub>* with *r* being the maximum number of extrapolated keys within a call of *E()*. This is handled within the feistel network class, as an instance lifecycle sees all blocks. Just in case you want to take a peek.
* [I-don't-even-know-any-more] Inspired by Rijndael, it does some monkey tricks with reversible matrix-mutators after each feistel round.
### Password to key ### Password to key
How does GCrypt transform a password to a key?.. How does GCrypt transform a password to a key?..
Well, it uses the included hash function [GHash](https://gitea.leonetienne.de/leonetienne/GCrypt/src/branch/feature/relaunch/GCryptLib/include/GCrypt/GHash.h). Well, it uses the included hash function [GHash](https://gitea.leonetienne.de/leonetienne/GCrypt/src/branch/master/GCryptLib/include/GCrypt/GHash.h).
### Hashing with GHash ### Hashing with GHash
GHash is a streaming hash function based on the GCipher. GHash is a streaming hash function based on the GCipher.
For all intents and purposes, it does the following: For all intents and purposes, it does the following:
You have a *Block b*, which is initialized with a static random distribution. You have a *Block b*, which is initialized with a static random distribution.
Once you give the GHash instance a data block to digest, it will use the GCipher to encrypt it, with itself as a key, and xor that onto *b*. Once you give the GHash instance a data block to digest, it will use the GCipher to encrypt it, with itself as a key, and xor that onto *b*.
(*b<sub>i</sub> = b<sub>i-1</sub> &#8853; E(key=b, data=b)*) (*b<sub>i</sub> = b<sub>i-1</sub> &#8853; E(key=b<sub>new</sub>, data=b<sub>new</sub>)*)
The lastest *b* represents the current result of the hash function. The lastest *b* represents the current result of the hash function.
GHash also supports a do-it-all wrapper method that takes a Flexblock (A block of arbitrary length), and returns a hashsum for it. GHash also supports a do-it-all wrapper method that takes a vector of blocks, and returns a hashsum for it.
This wrapper function adds an additional block including the length of the input. This wrapper function is used to transform Passwords to Keys. This wrapper function adds an additional block including the length of the input, if provided. This wrapper function is used to transform Passwords to Keys.
### GPrng...? ### GPrng...?
Whilst we're at it, why not implement a pseudo-random number generator based on GHash aswell. So here it is, [GPrng](https://gitea.leonetienne.de/leonetienne/GCrypt/src/branch/feature/relaunch/GCryptLib/include/GCrypt/GPrng.h). Whilst we're at it, why not implement a pseudo-random number generator based on GHash aswell. So here it is, [GPrng](https://gitea.leonetienne.de/leonetienne/GCrypt/src/branch/master/GCryptLib/include/GCrypt/GPrng.h).
GPrng is really nothing special. I just wanted to implement it, mainly to visualize the GCiphers entropy. GPrng is really nothing special. I just wanted to implement it, mainly to visualize the GCiphers entropy.
GPrng basically does the following: It creates a GHash instance, which initially digests the prng's seed. This produces a hash result, which is one block in size. GPrng basically does the following: It creates a GHash instance, which initially digests the prng's seed. This produces a hash result, which is one block in size.
@ -140,30 +148,30 @@ future output.
#### Single-block diffusion #### Single-block diffusion
`"Hello :3"` in binary, and it's ciphertext: `"Hello :3"` in binary, and it's ciphertext:
!["Hello :3" in binary](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-singleblock-diffusion-input.bmp.png) ![Hello :3 in binary](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-singleblock-diffusion-input.bmp.png)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Ciphertext 1](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-singleblock-diffusion-output.bmp.png) ![Ciphertext 1](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-singleblock-diffusion-output.bmp.png)
Now, let's flip a single bit in the input: Now, let's flip a single bit in the input:
One bit flipped, and again the corresponding ciphertext: One bit flipped, and again the corresponding ciphertext:
![One bit flipped](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-singleblock-diffusion-input-flip.bmp.png) ![One bit flipped](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-singleblock-diffusion-input-flip.bmp.png)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Ciphertext for flipped bit](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-singleblock-diffusion-output-flip.bmp.png) ![Ciphertext for flipped bit](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-singleblock-diffusion-output-flip.bmp.png)
Let's gif them together, to better see the difference: Let's gif them together, to better see the difference:
![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-singleblock-diffusion-input.gif) ![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-singleblock-diffusion-input.gif)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-singleblock-diffusion-output.gif) ![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-singleblock-diffusion-output.gif)
As shown, flipping even a single bit, affects the entire ciphertext. As shown, flipping even a single bit, affects the entire ciphertext.
#### What about input longer than a single block? #### What about input longer than a single block?
Input, and ciphertext: Input, and ciphertext:
![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-multiblock-diffusion-input.gif) ![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-multiblock-diffusion-input.gif)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-multiblock-diffusion-output.gif) ![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-multiblock-diffusion-output.gif)
Notice how the ciphertext doesn't change until the block containing the bitflip is reached? This is a limitation of cipher block chaining. Notice how the ciphertext doesn't change until the block containing the bitflip is reached? This is a limitation of cipher block chaining.
@ -171,11 +179,11 @@ Notice how the ciphertext doesn't change until the block containing the bitflip
How non-transparent is the cipher with extreme inputs? Even with a super problematic key?: How non-transparent is the cipher with extreme inputs? Even with a super problematic key?:
Input, key, and ciphertext: Input, key, and ciphertext:
![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-extreme-input-diffusion-input.gif) ![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-extreme-input-diffusion-input.gif)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Key](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-extreme-input-diffusion-key.bmp.png) ![Key](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-extreme-input-diffusion-key.bmp.png)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-extreme-input-diffusion-output.gif) ![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-extreme-input-diffusion-output.gif)
Notice how even cleartexts that are completely uniform, with a key that is almost just zeores, will still produce ambiguous ciphertexts. Notice how even cleartexts that are completely uniform, with a key that is almost just zeores, will still produce ambiguous ciphertexts.
@ -183,18 +191,18 @@ Notice how even cleartexts that are completely uniform, with a key that is almos
Check it out, here are the distributions of a few different getter-methods, some in black/white, some in grayscale, some in color. Check it out, here are the distributions of a few different getter-methods, some in black/white, some in grayscale, some in color.
Blackwhite - GetBit(), Grayscale - GetRandom<T>(), and Grayscale - operator(): Blackwhite - GetBit(), Grayscale - GetRandom<T>(), and Grayscale - operator():
![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-prng-distribution-blackwhite.bmp.png) ![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-prng-distribution-blackwhite.bmp.png)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Key](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-prng-distribution-getrandom-grayscale.bmp.png) ![Key](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-prng-distribution-getrandom-grayscale.bmp.png)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-prng-distribution-operator-grayscale.bmp.png) ![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-prng-distribution-operator-grayscale.bmp.png)
Color - GetRandom<T>(), Color - operator(), and Color - GetBlock(): Color - GetRandom<T>(), Color - operator(), and Color - GetBlock():
![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-prng-distribution-getrandom-color.bmp.png) ![Input](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-prng-distribution-getrandom-color.bmp.png)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Key](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-prng-distribution-operator-color.bmp.png) ![Key](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-prng-distribution-operator-color.bmp.png)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/feature/relaunch/GCryptLib/visualizations/visualize-prng-distribution-getblock-color.bmp.png) ![Ciphertext](https://gitea.leonetienne.de/leonetienne/GCrypt/raw/branch/master/GCryptLib/visualizations/visualize-prng-distribution-getblock-color.bmp.png)
## Noteworthy: ## Noteworthy:
* This is no fixed algorithm. Newer versions may very well be unable to decrypt ciphertexts encrypted with earlier versions. * This is no fixed algorithm. Newer versions may very well be unable to decrypt ciphertexts encrypted with earlier versions.