Skip to content

Leios crypto #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: cryptography
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ for language, tools in languages_to_import.items():

Export('env')

env['CFLAGS'] = '-Wall -Wextra -Werror'
env['CXXFLAGS'] = '-std=c++17'
env['CCFLAGS'] = '-Wall -Wextra -Werror -pedantic -Wconversion'
env['CFLAGS'] = '-std=gnu99'
env['CXXFLAGS'] = '-std=c++17 -Wold-style-cast'
env['ASFLAGS'] = '--64'
env['COCONUTFLAGS'] = '--target 3.8'

Expand Down
6 changes: 3 additions & 3 deletions contents/IFS/code/c/IFS.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,18 @@ void chaos_game(struct point *in, size_t in_n, struct point *out,
}

int main() {
const int point_count = 10000;
const size_t point_count = 10000;

struct point shape_points [3] = {{0.0,0.0}, {0.5,sqrt(0.75)}, {1.0,0.0}};
struct point out_points[point_count];

srand(time(NULL));
srand((unsigned int)time(NULL));

chaos_game(shape_points, 3, out_points, point_count);

FILE *fp = fopen("sierpinksi.dat", "w+");

for (int i = 0; i < point_count; ++i) {
for (size_t i = 0; i < point_count; ++i) {
fprintf(fp, "%f\t%f\n", out_points[i].x, out_points[i].y);
}

Expand Down
9 changes: 5 additions & 4 deletions contents/approximate_counting/code/c/approximate_counting.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ double increment(double v, double a)
// It returns n(v, a), the approximate count
double approximate_count(size_t n_items, double a)
{
int v = 0;
double v = 0;
for (size_t i = 0; i < n_items; ++i) {
v = increment(v, a);
}
Expand All @@ -61,9 +61,10 @@ void test_approximation_count(size_t n_trials, size_t n_items, double a,
for (size_t i = 0; i < n_trials; ++i) {
sum += approximate_count(n_items, a);
}
double avg = sum / n_trials;
double avg = sum / (double)n_trials;

if (fabs((avg - n_items) / n_items) < threshold){
double items = (double)n_items;
if (fabs((avg - items) / items) < threshold){
printf("passed\n");
}
else{
Expand All @@ -73,7 +74,7 @@ void test_approximation_count(size_t n_trials, size_t n_items, double a,

int main()
{
srand(time(NULL));
srand((unsigned int)time(NULL));

printf("[#]\nCounting Tests, 100 trials\n");
printf("[#]\ntesting 1,000, a = 30, 10%% error\n");
Expand Down
16 changes: 8 additions & 8 deletions contents/cooley_tukey/code/c/fft.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void fft(double complex *x, size_t n) {
memset(y, 0, sizeof(y));
fftw_plan p;

p = fftw_plan_dft_1d(n, (fftw_complex*)x, (fftw_complex*)y,
p = fftw_plan_dft_1d((int)n, (fftw_complex*)x, (fftw_complex*)y,
FFTW_FORWARD, FFTW_ESTIMATE);

fftw_execute(p);
Expand All @@ -27,7 +27,7 @@ void dft(double complex *X, const size_t N) {
for (size_t i = 0; i < N; ++i) {
tmp[i] = 0;
for (size_t j = 0; j < N; ++j) {
tmp[i] += X[j] * cexp(-2.0 * M_PI * I * j * i / N);
tmp[i] += X[j] * cexp(-2.0 * M_PI * I * (double)j * (double)i / (double)N);
}
}

Expand All @@ -49,7 +49,7 @@ void cooley_tukey(double complex *X, const size_t N) {
cooley_tukey(X + N / 2, N / 2);

for (size_t i = 0; i < N / 2; ++i) {
X[i + N / 2] = X[i] - cexp(-2.0 * I * M_PI * i / N) * X[i + N / 2];
X[i + N / 2] = X[i] - cexp(-2.0 * I * M_PI * (double)i / (double)N) * X[i + N / 2];
X[i] -= (X[i + N / 2]-X[i]);
}
}
Expand All @@ -58,7 +58,7 @@ void cooley_tukey(double complex *X, const size_t N) {
void bit_reverse(double complex *X, size_t N) {
for (size_t i = 0; i < N; ++i) {
size_t n = i;
int a = i;
size_t a = i;
int count = (int)log2((double)N) - 1;

n >>= 1;
Expand All @@ -67,7 +67,7 @@ void bit_reverse(double complex *X, size_t N) {
count--;
n >>= 1;
}
n = (a << count) & ((1 << (int)log2((double)N)) - 1);
n = (a << count) & (size_t)((1 << (size_t)log2((double)N)) - 1);

if (n > i) {
double complex tmp = X[i];
Expand All @@ -81,8 +81,8 @@ void iterative_cooley_tukey(double complex *X, size_t N) {
bit_reverse(X, N);

for (int i = 1; i <= log2((double)N); ++i) {
size_t stride = pow(2, i);
double complex w = cexp(-2.0 * I * M_PI / stride);
size_t stride = (size_t)pow(2, i);
double complex w = cexp(-2.0 * I * M_PI / (double)stride);
for (size_t j = 0; j < N; j += stride) {
double complex v = 1.0;
for (size_t k = 0; k < stride / 2; ++k) {
Expand All @@ -105,7 +105,7 @@ void approx(double complex *X, double complex *Y, size_t N) {
}

int main() {
srand(time(NULL));
srand((unsigned int)time(NULL));
double complex x[64], y[64], z[64];
for (size_t i = 0; i < 64; ++i) {
x[i] = rand() / (double) RAND_MAX;
Expand Down
4 changes: 2 additions & 2 deletions contents/cooley_tukey/code/cpp/fft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void cooley_tukey(Iter first, Iter last) {

// now combine each of those halves with the butterflies
for (int k = 0; k < size / 2; ++k) {
auto w = std::exp(complex(0, -2.0 * pi * k / size));
auto w = std::exp(complex(0, -2.0 * pi * k / static_cast<double>(size)));

auto& bottom = first[k];
auto& top = first[k + size / 2];
Expand All @@ -78,7 +78,7 @@ void sort_by_bit_reverse(Iter first, Iter last) {
b = (((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2));
b = (((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4));
b = (((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8));
b = ((b >> 16) | (b << 16)) >> (32 - std::uint32_t(log2(size)));
b = ((b >> 16) | (b << 16)) >> (32 - std::uint32_t(log2(static_cast<double>(size))));
if (b > i) {
swap(first[b], first[i]);
}
Expand Down
84 changes: 55 additions & 29 deletions contents/cryptography/cryptography.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Humans have almost always been interested in sending secret messages that only the sender and receiver understand.
The reason for this is obvious: secret messages should remain secret.
The easiest way for this to happen is to talk behind closed doors, but that simply doesn't work if the the sender and receiver are separated by a significant distance.
The easiest way for this to happen is to talk behind closed doors, but that simply doesn't work if the sender and receiver are separated by a significant distance.
In this case, they need to rely on a messenger or mailman to send the message.

For simplicity, let's assume they are sending a written letter for the purpose of negotiating war tactics in ancient Greece or Rome.
Expand All @@ -17,25 +17,47 @@ In this way, the message would seem like utter gobbledygook to anyone other than
It doesn't matter if the messenger is evil.
They cannot read the message anyway.
It's also fine if the message is replaced, because then the receiver won't be able to properly decode the message and can just ask for another message to be sent (probably on another path with a different messenger).
Unsurprisingly, a very early method of encryption was supposedly developed by Julius Caeser and called the "Caesar Cipher."
Unsurprisingly, a very early method of encryption was supposedly developed by Julius Caeser and called the "Caesar Cipher" {{ "ceasar_cipher_wiki" | cite }}.
Here, every character in the message is replaced by another character based on some pre-defined table or chart that only the sender and receiver have.
The table is created by simply rotating the alphabet by $$n$$ spaces, where $$n$$ is chosen in a discussion between the sender and receiver before-hand.
| $$n$$ | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z |
| 2 | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z | a | b |
| 14 | o | p | q | r | s | t | u | v | w | x | y | z | a | b | c | d | e | f | g | h | i | j | k | l | m | n |
| 18 | s | t | u | v | w | x | y | z | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r |
| 21 | v | w | x | y | z | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u |
| 24 | y | z | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x |

| $$n$$ | 0 | 2 | 14 | 18 | 21 | 24 |
| ----- | - | - | -- | -- | -- | -- |
| a | a | c | o | s | v | y |
| b | b | d | p | t | w | z |
| c | c | e | q | u | x | a |
| d | d | f | r | v | y | b |
| e | e | g | s | w | z | c |
| f | f | h | t | x | a | d |
| g | g | i | u | y | b | e |
| h | h | j | v | z | c | f |
| i | i | k | w | a | d | g |
| j | j | l | x | b | e | h |
| k | k | m | y | c | f | i |
| l | l | n | z | d | g | j |
| m | m | o | a | e | h | k |
| n | n | p | b | f | i | l |
| o | o | q | c | g | j | m |
| p | p | r | d | h | k | n |
| q | q | s | e | i | l | o |
| r | r | t | f | j | m | p |
| s | s | u | g | k | n | q |
| t | t | v | h | l | o | r |
| u | u | w | i | m | p | s |
| v | v | x | j | n | q | t |
| w | w | y | k | o | r | u |
| x | x | z | l | p | s | v |
| y | y | a | m | q | t | w |
| z | z | b | n | r | u | x |

It is certainly not the most complicated scheme out there, but it is generally the first encryption scheme people come up with when trying to encode secret messages to one another.
Honestly, I remember sending messages back and forth to friends in elementary school, but we would never provide the necessary table to decode the message.
Instead, we would provide enough text that they could find the table themselves from context.
If a bunch of elementary school kids can figure out how to break this encryption scheme, it cannot be too robust.
In fact, it's interesting to see how the field of cryptography has grown since the Caesar cipher was developed.
In the cryptographic literature, there is always a sender, receiver, and eavesdropper.
For some reason beyond my own comprehension, these three people are almost always given the names Alice (sender), Bob (receiver), and Eve (attacker or eavesdropper).
For some reason beyond my own comprehension, the first two people are almost always given the names Alice (sender) and Bob (receiver).
Meanwhile, the attacker or eavesdropper is usually called either Eve or Charlie
These names are consistent even with quantum cryptography, so they are here to stay.

In general, there are two different types of encryption: symmetric and asymmetric.
Expand All @@ -44,52 +66,56 @@ Both of which are described in the following sections.
Cryptographic systems are a cornerstone to modern information technology and lie at the heart of everything from WiFi to online banking.
If an attacker manages to crack modern cryptographic algorithms, they could cause serious damage.
For this reason, it is important to keep a few things in mind:
* Because cryptography has become such an advanced field cryptography systems should be analyzed by trained professionals and have to go under extensive testing and vetting.
Meaning whenever possible use a widely accepted cryptography library instead of writing your own cypher.
* Kerckhoffs's principle says that when determining the robustness of a cryptography system it should be assumed that the attacker knows the encryption and decryption algorithm.
* Because cryptography has become such an advanced field cryptographic systems should be analyzed by trained professionals and have undergo extensive testing and vetting.
This means that whenever possible, one should use a widely accepted cryptography library instead of writing their own cypher.
* Kerckhoffs's principle says that when determining the robustness of a cryptographic system it should be assumed that the attacker knows the encryption and decryption algorithm {{ "Kerckhoffs_principle_wiki" | cite }}.
This does not include any pre-shared or secret keys.
* With the advances in technology cryptography often hits its limits.
* With the advances in technology, cryptography often hits its limits.
Many formerly state-of-the-art hashing algorithms have become obsolete because the computers used to crack them have gotten faster and better.
The keys for RSA have to be longer or different and stronger algorithms have to be used.
Another field that cryptography will have to face is Quantum Computing.
Another field that cryptography will have to face is [quantum computing](../quantum_information/quantum_information.md).
Quantum computers will have a big impact on cryptography and especially asymmetric cryptography.
This whole set of problems is summarized in the field of post-quantum cryptography.
This whole set of problems is summarized in the field of post-quantum cryptography {{ "post-quantum_crypto_wiki" | cite }}.

## Symmetric Cryptography

Symmetric cryptography is called symmetric because the key that is used is the same for encrypting and decrypting.
For this to work Alice and Bob both need the same key, which they have to share before communicating.
Some examples for symmetric cryptography are:
* **Ceasar Cipher**: Alice and Bob rotate the alphabet by $$n$$ characters and use that as a table to encode and decode their message.
* **Rot13**: This is a special case of the Caeser Cipher where the alphabet is rotated by 13, hence the name "Rot13."
* **Permutation Cipher**: Here you choose a permutation $$\pi$$ (i.e. $$\pi=(3,1,2,4)$$) and reorder the the letters according to that $$\pi$$ which is the key.
* **XOR encryption**: This method works on bit strings and combines the message and a key of equal bit length with the XOR operator.
* **Ceasar Cipher**: Alice and Bob rotate the alphabet by $$n$$ characters and use that as a table to encode and decode their message {{ "ceasar_cipher_wiki" | cite }}.
* **Rot13**: This is a special case of the Caeser Cipher where the alphabet is rotated by 13, hence the name "Rot13" {{ "rot13_wiki" | cite }}
* **Permutation Cipher**: Here we choose a permutation $$\pi$$ (i.e. $$\pi=(3,1,2,4)$$) and reorder the the letters according to that $$\pi$$ which is the key {{ "CC_permutation" | cite }}.
* **XOR encryption**: This method works on bit strings and combines the message and a key of equal bit length with the XOR operator {{ "xor_cipher_wiki" | cite }}.
To decrypt, simply XOR again with the same key.
* **DES or Data Encryption Standard**: This is a newer encryption algorithm which was standardized in 1977.
* **DES or Data Encryption Standard**: This is a newer encryption algorithm which was standardized in 1977 {{ "DES_wiki" | cite }}.
It has since been deemed insecure and is superseded by AES.
* **AES or Advanced Encryption Standard**: The actual algorithm is called "Rijndael".
Like with XOR or DES you generate a bit string (depending on which AES you use 128/192 or 256 bit long) which is your key.
* **Blowfish**: This algorithm also was a good contender for the AES but lost to Rijndael.
* **AES or Advanced Encryption Standard**: The actual algorithm is called "Rijndael" {{ "AES_wiki" | cite }}.
Like with XOR or DES we generate a bit string (depending on which AES you use 128/192 or 256 bit long) which is your key.
* **Blowfish**: This algorithm was also a good contender for the AES but lost to Rijndael {{ "blowfish_cipher_wiki" | cite }}.

This section is currently a work-in-progress, and all of these methods will have corresponding chapters in the near future.

## Asymmetric Cryptography

Asymmetric cryptography is sometimes called "public key cryptography" (or PK cryptography in short) because Bob and Alice both need a shared public key and a private key they keep to themselves.
These algorithms are called asymmetric because what is encrypted with the public key can only be decrypted with the private key and vice versa.
This can be used for a number of different applications, like digital signing, encrypted communication or secretly sharing keys.
This can be used for a number of different applications, like digital signing, encrypted communication, or secretly sharing keys.
For example, if Alice wants to send a message to Bob and this message has to be kept private, Alice will encrypt the message with Bob's public key.
Now only Bob can decrypt the message again and read it.
If Charlie were to alter Alice's message, Bob couldn't decrypt it anymore.
If Bob wants to make sure the message is actually from Alice, Alice can encrypt the already encrypted message with her private key again.
This is to keep Charlie from sending forged or altered messages since Bob couldn't decrypt that layer with Alice's public key.
Some examples for public key cryptography:
* **RSA**: This algorithm calculates a public and a private key from two very large primes.
* **RSA**: This algorithm calculates a public and a private key from two very large primes {{ "RSA_wiki" | cite }}.
It is (hopefully) near impossible to factor the product of two such primes in a feasible amount of time.
* **ECC or Elliptic-curve cryptography**: Here you calculate the private and public key from two points on an elliptic curve.
* **ECC or Elliptic-curve cryptography**: Here you calculate the private and public key from two points on an elliptic curve {{ "ECC_crypto_wiki" | cite }}.
This has the positive side effect that you need smaller numbers than non-ECC algorithms like RSA to achieve the same level of security.

This section is currently a work-in-progress. These methods will also have corresponding chapters in the near future.

### Bibliography

{% references %} {% endreferences %}

<script>
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
</script>
Expand Down
33 changes: 33 additions & 0 deletions contents/cryptography/res/table.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
function print_table(a::Array{T, 2},
header::Vector{String}) where T <: Union{Char, String}
print(" | ")
for i = 1:length(header)
print(string(header[i]), " | ")
end
println()

print(" | ")
for i = 1:length(header)
print("---", " | ")
end
println()

for i = 1:size(a)[1]
print(" | ")
for j = 1:size(a)[2]
print(string(a[i,j]), " | ")
end
println()
end
end

alphabet = [char for char = 'a':'z']
offsets = Int.([0, 0, 2, 14, 18, 21, 24])
alphabet_array = Array{Char}(undef, 26, length(offsets))

for i = 1:length(offsets)
alphabet_array[:,i] = vcat(alphabet[offsets[i]+1:26],alphabet[1:offsets[i]])
end

header = vcat(string.(offsets))
print_table(alphabet_array, header)
2 changes: 1 addition & 1 deletion contents/forward_euler_method/code/c/euler.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ void solve_euler(double timestep, double *result, size_t n) {
int check_result(double *result, size_t n, double threshold, double timestep) {
int is_approx = 1;
for (size_t i = 0; i < n; ++i) {
double solution = exp(-3.0 * i * timestep);
double solution = exp(-3.0 * (double)i * timestep);
if (fabs(result[i] - solution) > threshold) {
printf("%f %f\n", result[i], solution);
is_approx = 0;
Expand Down
2 changes: 1 addition & 1 deletion contents/forward_euler_method/code/cpp/euler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ template <typename Iter>
bool check_result(Iter first, Iter last, double threshold, double timestep) {
auto it = first;
for (size_t idx = 0; it != last; ++idx, ++it) {
double solution = std::exp(-3.0 * idx * timestep);
double solution = std::exp(-3.0 * static_cast<double>(idx) * timestep);
if (std::abs(*it - solution) > threshold) {
std::cout << "We found a value outside the threshold; the " << idx
<< "-th value was " << *it << ", but the expected solution was "
Expand Down
Loading