Block-Cipher (Lösung)
Code aus der Vorlesung
Den folgenden Code haben wir zusammen erarbeitet.
Wichtig: Nützlicher als das fertige Programm ist das Durcharbeiten der in der Vorlesung gezeigten Schritt-für-Schritt-Vorgehensweise. Der Code dort ist zwar nicht mit dem Code aus der Vorlesung identisch; er wird jedoch Schritt für Schritt entwickelt und ist ebenfalls eine vollständige Lösung.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#define BLOCKSIZE 3
#define ZEROCHAR '0'
void extract_block(string cleartext, int start_pos, char target[]);
void print_block(string block);
void permute_block(string current_block, int key_arr[]);
int validate_key(int key_arr[]);
int main(int argc, string argv[])
{
// Der Permutationsschlüssel “201” bedeutet:
// Position 0 geht nach 2, Position 1 geht nach 0,
// Position 2 geht nach 1. Für den ersten Block
// heißt das: HAL -> ALH
/*
HAL <= Quelle
012
201 <= Permutation = Index in der "Quelle"
012 <= Pos. 2 im String geht an Stelle 0 ("Ziel")
*/
// ./permute 201 VSCODE
if (argc != 3)
{
printf("Usage: ./permute Permutation String\n");
return 1;
}
string key_string = argv[1];
string cleartext = argv[2];
int key_arr[3];
printf("Key: ");
// TODO refactor into separate function
for (int i = 0; i < BLOCKSIZE; i++)
{
key_arr[i] = key_string[i] - ZEROCHAR;
printf("%i ", key_arr[i]);
}
printf("\n");
if(! validate_key(key_arr))
{
printf("Key is invalid!\n");
return 2;
}
//printf("Input: %s %s\n", permutation, cleartext);
/*
FOR pos = 0 BIS length(cleartext) SCHRITTWEITE SIZE
AUSGABE "Block beginnt bei " + pos
FOR pos_im_block = 0 BIS < 3 SCHRITTWEITE 1
AUSGABE cleartext[ pos + pos_im_block ]
AUSGABE " "
*/
for (int pos = 0; pos < strlen(cleartext); pos += BLOCKSIZE)
{
char current_block[3];
extract_block(cleartext, pos, current_block);
printf("BEFORE: ");
print_block(current_block);
// permute block
/*
HAL <= Quelle
012
201 <= Permutation = Index in der "Quelle"
012 <= Pos. 2 im String geht an Stelle 0 ("Ziel")
*/
// overwrite current block with permuted block
permute_block(current_block, key_arr);
printf(" - AFTER: ");
print_block(current_block);
printf("\n");
}
printf("\n");
}
void extract_block(string cleartext, int start_pos, char target[])
{
for (int pos_in_block = 0; pos_in_block < BLOCKSIZE; pos_in_block++)
{
target[pos_in_block] = cleartext[ start_pos + pos_in_block ];
}
}
void print_block(string block)
{
for (int i = 0; i < BLOCKSIZE; i++)
{
printf("%c", block[i]);
}
}
// overwrite current block with permuted block
/*
current_block has size BLOCKSIZE
key_arr[0] = 2 means: take element 2 from
current_block and place
it in position 0
*/
void permute_block(string current_block, int key_arr[])
{
char temp[3];
for (int i=0; i < BLOCKSIZE; i++)
{
temp[i] = current_block[key_arr[i]];
}
for (int i=0; i < BLOCKSIZE; i++)
{
current_block[i] = temp[i];
}
}
// assume key_arr has length 3
int validate_key(int key_arr[])
{
// div. Prüfungen
int anzahl_der_zahlen[3] = {0, 0, 0};
for (int i = 0; i < BLOCKSIZE; i++)
{
if (key_arr[i] >= BLOCKSIZE || key_arr[i] < 0)
{
return 0;
}
// zähle wie oft jede Zahl vorkommt (erhöhe um 1)
anzahl_der_zahlen[ key_arr[i] ]++;
}
for (int i = 0; i < BLOCKSIZE; i++)
{
if(anzahl_der_zahlen[i] != 1)
{
return 0;
}
}
return 1;
}