mirror of
https://github.com/mfocko/blog.git
synced 2024-11-10 08:19:07 +01:00
Matej Focko
a868efaee6
* Switch the archiving from the ‹zip› to ‹tar.gz› and ‹tar.bz2› * Adjust the static files to have consistent paths Signed-off-by: Matej Focko <me@mfocko.xyz>
169 lines
4.6 KiB
Markdown
169 lines
4.6 KiB
Markdown
---
|
|
id: seminar-05-06
|
|
title: 5th and 6th seminar
|
|
description: |
|
|
200IQ encryption.
|
|
---
|
|
|
|
For this bonus you can get at maximum 2.5 K₡.
|
|
|
|
[Source](pathname:///files/pb071/bonuses/05-06.tar.gz)
|
|
|
|
## Introduction
|
|
|
|
In this bonus you will implement few functions that will be used together for
|
|
implementing a very special cipher.
|
|
|
|
### Task no. 1: Reverse (0.5 K₡)
|
|
|
|
Write a function `char* reverse(const char* text)` that returns copy of the input
|
|
string in reversed order (also uppercase).
|
|
|
|
In case you are given `NULL`, return `NULL`.
|
|
|
|
Example (more in tests):
|
|
|
|
```c
|
|
char* reversed = reverse("Hello world!");
|
|
|
|
printf("%s\n", reversed);
|
|
// "!DLROW OLLEH"
|
|
|
|
if (reversed != NULL) {
|
|
free(reversed);
|
|
}
|
|
```
|
|
|
|
### Task no. 2: Vigenère (0.5 K₡)
|
|
|
|
Vigenère cipher is similar to the Caesar cipher, but you also have a key that is
|
|
used for encrypting (or decrypting).
|
|
|
|
Your task is to write two functions:
|
|
|
|
- `char* vigenere_encrypt(const char* key, const char* text)` for encrypting
|
|
- `char* vigenere_decrypt(const char* key, const char* text)` for decrypting
|
|
|
|
In both of those you should return uppercase characters.
|
|
|
|
Meaning of the parameters you are given:
|
|
|
|
- `key` - String that represents key that is used for \*crypting. It consists of
|
|
one word and can have only characters of the alphabet. Does not matter if they
|
|
are uppercase or lowercase.
|
|
- `text` - String that is to be \*crypted.
|
|
|
|
Function returns address of the encrypted (or decrypted) string. Or `NULL` in case
|
|
error occurs.
|
|
|
|
Example:
|
|
|
|
```c
|
|
char *encrypted = vigenere_encrypt("CoMPuTeR", "Hello world!");
|
|
|
|
printf("%s\n", encrypted);
|
|
// "JSXAI PSINR!"
|
|
|
|
if (encrypted != NULL) {
|
|
free(encrypted)
|
|
}
|
|
```
|
|
|
|
#### Bonus part (0.5 K₡)
|
|
|
|
If you can utilize helper function that would do both encrypting and decrypting,
|
|
you can gain 0.5 K₡.
|
|
|
|
Usage of `true`/`false` to decide path in code is prohibited. It leads to merging
|
|
of both functions into one. Point of this part is to discover a way to do this
|
|
generically in such way that there are no separate paths for one or the other. One
|
|
function with no branching for both of them, parametrization is your friend :)
|
|
|
|
### Task no. 3: Bit madness (0.5 K₡)
|
|
|
|
This is a state of the art crypto. Please do not share :)
|
|
|
|
For encrypting:
|
|
|
|
1. Split the character that is to be encrypted in halves (4 and 4 bits each).
|
|
2. Bits in 1st half are to be split into pairs. Swap bits in those pairs.
|
|
3. Then use the 4 bits that you created in the 2nd step for `XOR` with the other
|
|
4 bits.
|
|
|
|
This simple and ingenious principle will be illustrated on the following example.
|
|
String we want to encrypt is `Hello world!`. We need to encrypt each letter separately,
|
|
so we will demonstrate on letter `H`:
|
|
|
|
1. Letter `H` is represented in ASCII as `72`.
|
|
|
|
`72` represented in binary is: `01001000`. So first 4 bits are: `0100` and last
|
|
4 bits are `1000`.
|
|
|
|
2. First half of bits (`0100`) consists of 2 pairs (`01` and `00`) which we swap
|
|
(`01 ~> 10` and `00 ~> 00`). That way we get `1000`.
|
|
|
|
3. That half is used for xor with the other 4 bits:
|
|
|
|
```
|
|
1000 // second half
|
|
XOR 1000 // first half after 2nd step
|
|
--------
|
|
0000
|
|
```
|
|
|
|
4. Now we combine both halves (first one is `1000`, which we got from the 2nd step
|
|
and second one is `0000`, which we got from the 3rd step) and get `10000000`,
|
|
which is encrypted character `H` using this method.
|
|
|
|
In case of decryption, reverse those steps.
|
|
|
|
Your task is to implement functions:
|
|
|
|
- `unsigned char* bit_encrypt(const char* text)`
|
|
- `char* bit_decrypt(const unsigned char* text)`
|
|
|
|
Example:
|
|
|
|
```c
|
|
unsigned char* encrypted = bit_encrypt("Hello world!");
|
|
|
|
for (int i = 0; i < 12;i++) {
|
|
printf("%x ", encrypted[i]);
|
|
//80 9c 95 95 96 11 bc 96 b9 95 9d 10
|
|
}
|
|
|
|
if (encrypted != NULL) {
|
|
free(encrypted);
|
|
}
|
|
```
|
|
|
|
### Task no. 4: All combined to BMP (0.5 K₡)
|
|
|
|
Authors of the BMP cipher are non-disclosed :)
|
|
|
|
Create pair of functions:
|
|
|
|
- `unsigned char* bmp_encrypt(const char* key, const char* text)`
|
|
- `char* bmp_decrypt(const char* key, const unsigned char* text)`
|
|
|
|
BMP cipher consists of following steps for encrypting:
|
|
|
|
1. Reverse the input string
|
|
2. Use Vigenere on the string you got from step #1
|
|
3. Use bit madness on the string you got from step #2
|
|
|
|
For decrypting, reverse the steps.
|
|
|
|
## Submitting
|
|
|
|
In case you have any questions, feel free to reach out to me.
|
|
|
|
---
|
|
|
|
Ideally submit the assignment through the merge request. Step-by-step tutorial is
|
|
present [here](../mr). For setting assignee my xlogin is `xfocko`.
|
|
|
|
In case you do not want to experiment on GitLab, send me the source code via email,
|
|
but please prefix subject with: `[PB071/14][seminar-05-06]`
|
|
|
|
Deadline for the submission of the bonus is **April 21th 24:00**.
|