blog/pb071/bonuses/05-06.md
Matej Focko 791b681548
fix(pb071): comment out broken links
Signed-off-by: Matej Focko <mfocko@redhat.com>
2023-09-07 20:13:43 +02:00

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**. -->