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 <cs50.h>
#include <stdio.h>
#include <string.h>

#define SIZE 3

void extract_block(string text, int start, char block[]);
void print_block(char block[]);
void permute_block(char block[], char key[]);
int validate_input(string text, char key[]);

// ./permue KEY PLAINTEXT
int main(int argc, string argv[])
{
    if (argc != 3)
    {
        printf("Usage: ./permute needs two parameters!\n");
        return 1;
    }

    string key =  argv[1];
    string text = argv[2];

    if(validate_input(text, key) != 0)
    {
        return 1;
    }

    printf("Key: %s - Input: %s\n", key, text);

   // Annahme: Länge muss Vielfaches von SIZE

   for (int i = 0, len = strlen(text); i < len; i += SIZE)
   {
        char block[SIZE];
        extract_block(text, i, block);
        // block[0] = H, block[1] = E, block[2] = L

        permute_block(block, key);
        print_block(block);

   }
}

void permute_block(char block[], char key[])
{
    int key_int[SIZE];
    for (int i = 0; i < SIZE; i++)
    {
        key_int[i] = key[i] - '0';
    }

    char temp[SIZE];

    for (int i = 0; i < SIZE; i++)
    {
        temp[ key_int[i] ] = block[ i ];
    }

    for (int i = 0; i < SIZE; i++)
    {
        block[i] = temp[i];
    }
}

void print_block(char block[])
{
    printf("%c", block[0]);
    printf("%c", block[1]);
    printf("%c", block[2]);
    printf(" - ");
}

void extract_block(string text, int start, char block[])
{
    for (int j = 0; j < SIZE ; j++)
    {
        block[j] = text[start + j];
    }
}

int validate_input(string text, char key[])
{
    if (strlen(text) % SIZE != 0)
    {
        printf("String muss ein Vielfaches von %i sein!\n", SIZE);
        return 1;
    }

    if (strlen(key) % SIZE != 0)
    {
        printf("Key muss die Länge %i haben!\n", SIZE);
        return 1;
    }

    for (int i = 0; i < SIZE; i++)
    {
        // SIZE ist ja 3, wir wollen aber max. Keys mit 2 zulassen, daher - 1
        if (key[i] < '0' || key[i] > ('0' + SIZE - 1) )
        {
            printf("Key muss aus Ziffern zwischen 0 und %i bestehen!\n", SIZE - 1);
            return 1;
        }
    }

    // wie oft kommt die Ziffer am Index vor, d.h. used[0] = 5 heißt: die 0 kam 5x vor
    int used[SIZE] = { 0 }; // belegt alles mit 0

    for (int i = 0; i < SIZE; i++)
    {
        int key_as_int = key[i] - '0'; // z.B. 2 wenn '2'
        used[key_as_int]++;
    }

    for (int i = 0; i < SIZE; i++)
    {
        if (used[i] != 1)
        {
            printf("Die Ziffer %i kommt nicht genau 1x vor!\n", i);
            return 1;
        }
    }
    return 0;
}