Szyfr Cezara w C - Implementacja Krok po Kroku

advertisement

Szyfr Cezara w Programowaniu C to fundamentalny projekt, który powinien opanować każdy student programowania w C. Ten tutorial zapewnia kompletną, działającą implementację ze szczegółowymi wyjaśnieniami każdego komponentu. Aby zrozumieć teoretyczne podstawy tego szyfru, odwiedź nasz Przewodnik Szyfru Cezara.

Krok 1: Dołączenie Wymaganych Bibliotek

Najpierw musimy dołączyć niezbędne biblioteki, które zapewniają funkcje do wejścia/wyjścia, manipulacji ciągów znaków i operacji na znakach.

#include <stdio.h>
#include <string.h>
#include <ctype.h>

Krok 2: Utworzenie Funkcji Szyfrowania

Funkcja szyfrowania przyjmuje ciąg tekstowy, wartość przesunięcia i bufor wynikowy. Przetwarza każdy znak, przesuwając litery przy zachowaniu znaków niealfabetycznych.

// Funkcja do szyfrowania tekstu używając szyfru Cezara
void encrypt(char *text, int shift, char *result) {
    int i;
    int length = strlen(text);

    for (i = 0; i < length; i++) {
        char ch = text[i];

        // Szyfrowanie wielkich liter
        if (ch >= 'A' && ch <= 'Z') {
            result[i] = ((ch - 'A' + shift) % 26) + 'A';
        }
        // Szyfrowanie małych liter
        else if (ch >= 'a' && ch <= 'z') {
            result[i] = ((ch - 'a' + shift) % 26) + 'a';
        }
        // Pozostawienie znaków niealfabetycznych bez zmian
        else {
            result[i] = ch;
        }
    }
    result[length] = '\0'; // Zakończenie ciągu znakiem null
}

Krok 3: Implementacja Funkcji Deszyfrowania

Deszyfrowanie to po prostu szyfrowanie z odwróconym przesunięciem. Obliczamy odwrotne przesunięcie i używamy naszej funkcji szyfrowania.

// Funkcja do deszyfrowania tekstu używając szyfru Cezara
void decrypt(char *text, int shift, char *result) {
    // Deszyfrowanie to szyfrowanie z ujemnym przesunięciem
    int decryptShift = 26 - (shift % 26);
    encrypt(text, decryptShift, result);
}

Krok 4: Budowa Funkcji Głównej

Funkcja główna zapewnia przyjazny interfejs menu, obsługuje walidację danych wejściowych i demonstruje zarówno szyfrowanie, jak i deszyfrowanie.

int main() {
    char text[1000];
    char result[1000];
    int shift = 3; // Domyślne przesunięcie Cezara

    // Przykład użycia
    printf("Demo Szyfru Cezara\n");
    printf("Wprowadź tekst: ");
    fgets(text, sizeof(text), stdin);

    // Usuń znak nowej linii jeśli istnieje
    if (text[strlen(text) - 1] == '\n') {
        text[strlen(text) - 1] = '\0';
    }

    // Zaszyfruj tekst
    encrypt(text, shift, result);
    printf("\nOryginalny: %s\n", text);
    printf("Zaszyfrowany: %s\n", result);

    // Odszyfruj tekst
    decrypt(result, shift, text);
    printf("Odszyfrowany: %s\n", text);

    return 0;
}

Kompletny Kod Programu

Oto kompletny, gotowy do kompilacji program szyfru Cezara, który łączy wszystkie powyższe kroki:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

// Funkcja do szyfrowania tekstu używając szyfru Cezara
void encrypt(char *text, int shift, char *result) {
    int i;
    int length = strlen(text);

    for (i = 0; i < length; i++) {
        char ch = text[i];

        // Szyfrowanie wielkich liter
        if (ch >= 'A' && ch <= 'Z') {
            result[i] = ((ch - 'A' + shift) % 26) + 'A';
        }
        // Szyfrowanie małych liter
        else if (ch >= 'a' && ch <= 'z') {
            result[i] = ((ch - 'a' + shift) % 26) + 'a';
        }
        // Pozostawienie znaków niealfabetycznych bez zmian
        else {
            result[i] = ch;
        }
    }
    result[length] = '\0'; // Zakończenie ciągu znakiem null
}

// Funkcja do deszyfrowania tekstu używając szyfru Cezara
void decrypt(char *text, int shift, char *result) {
    // Deszyfrowanie to szyfrowanie z ujemnym przesunięciem
    int decryptShift = 26 - (shift % 26);
    encrypt(text, decryptShift, result);
}

// Funkcja do wyświetlania menu i pobierania wyboru użytkownika
int getChoice() {
    int choice;
    printf("\n=== Program Szyfru Cezara ===\n");
    printf("1. Zaszyfruj tekst\n");
    printf("2. Odszyfruj tekst\n");
    printf("3. Wyjście\n");
    printf("Wprowadź swój wybór (1-3): ");
    scanf("%d", &choice);
    return choice;
}

int main() {
    char text[1000];
    char result[1000];
    int shift;
    int choice;

    printf("Witamy w Programie Szyfru Cezara!\n");

    do {
        choice = getChoice();

        switch(choice) {
            case 1:
                printf("\nWprowadź tekst do zaszyfrowania: ");
                getchar(); // Wyczyść bufor
                fgets(text, sizeof(text), stdin);

                // Usuń znak nowej linii jeśli istnieje
                if (text[strlen(text) - 1] == '\n') {
                    text[strlen(text) - 1] = '\0';
                }

                printf("Wprowadź wartość przesunięcia (1-25): ");
                scanf("%d", &shift);

                // Walidacja wartości przesunięcia
                if (shift < 1 || shift > 25) {
                    printf("Nieprawidłowa wartość przesunięcia! Używam domyślnego przesunięcia 3.\n");
                    shift = 3;
                }

                encrypt(text, shift, result);
                printf("\nTekst oryginalny: %s\n", text);
                printf("Tekst zaszyfrowany: %s\n", result);
                break;

            case 2:
                printf("\nWprowadź tekst do odszyfrowania: ");
                getchar(); // Wyczyść bufor
                fgets(text, sizeof(text), stdin);

                // Usuń znak nowej linii jeśli istnieje
                if (text[strlen(text) - 1] == '\n') {
                    text[strlen(text) - 1] = '\0';
                }

                printf("Wprowadź wartość przesunięcia użytą do szyfrowania (1-25): ");
                scanf("%d", &shift);

                // Walidacja wartości przesunięcia
                if (shift < 1 || shift > 25) {
                    printf("Nieprawidłowa wartość przesunięcia! Używam domyślnego przesunięcia 3.\n");
                    shift = 3;
                }

                decrypt(text, shift, result);
                printf("\nTekst zaszyfrowany: %s\n", text);
                printf("Tekst odszyfrowany: %s\n", result);
                break;

            case 3:
                printf("\nDziękujemy za korzystanie z Programu Szyfru Cezara!\n");
                break;

            default:
                printf("\nNieprawidłowy wybór! Spróbuj ponownie.\n");
        }
    } while (choice != 3);

    return 0;
}

Jak Działa Program

Program składa się z kilku kluczowych komponentów, które współpracują ze sobą:

  • Funkcja Szyfrowania - Przyjmuje tekst wejściowy i wartość przesunięcia, przekształca każdą literę przesuwając ją do przodu w alfabecie
  • Funkcja Deszyfrowania - Odwraca proces szyfrowania przesuwając litery do tyłu
  • Funkcja Główna - Zapewnia interfejs użytkownika z systemem menu dla operacji szyfrowania/deszyfrowania

Kluczowe Cechy Implementacji:

  • Poprawnie obsługuje wielkie i małe litery
  • Zachowuje spacje, cyfry i znaki specjalne
  • Używa arytmetyki modulo do zawijania alfabetu
  • Zawiera walidację danych wejściowych i obsługę błędów
  • Interaktywny system menu dla przyjaznego użytkowania
  • Właściwa obsługa ciągów znaków z zakończeniem null

Kompilacja i Wykonanie

Aby skompilować i uruchomić ten program na większości systemów, użyj następujących poleceń:

gcc -o caesar_cipher caesar_cipher.c
./caesar_cipher

# W systemie Windows:
gcc -o caesar_cipher.exe caesar_cipher.c
caesar_cipher.exe

Przykład Wyjścia Programu

Oto co zobaczysz uruchamiając program:

Witamy w Programie Szyfru Cezara!

=== Program Szyfru Cezara ===
1. Zaszyfruj tekst
2. Odszyfruj tekst
3. Wyjście
Wprowadź swój wybór (1-3): 1

Wprowadź tekst do zaszyfrowania: Witaj Świecie!
Wprowadź wartość przesunięcia (1-25): 3

Tekst oryginalny: Witaj Świecie!
Tekst zaszyfrowany: Zlwdm Ăzlhflh!

Zarządzanie Pamięcią i Bezpieczeństwo

Ta implementacja używa tablic znaków o stałym rozmiarze, aby uniknąć złożoności dynamicznej alokacji pamięci. Program zawiera odpowiednie sprawdzanie granic i zakończenie null ciągów znaków, aby zapobiec przepełnieniu bufora. Do użytku produkcyjnego rozważ implementację dynamicznej alokacji pamięci dla obsługi większych tekstów.

Kwestie Bezpieczeństwa

Pamiętaj, że szyfr Cezara to prosty szyfr podstawieniowy i zapewnia minimalne bezpieczeństwo. Jest łatwo łamany przez analizę częstotliwości lub ataki brute force. Ta implementacja jest przeznaczona do celów edukacyjnych i zrozumienia podstawowych koncepcji kryptograficznych.

Cele Edukacyjne

Implementacja szyfru Cezara w C uczy kilku fundamentalnych koncepcji programowania:

  • Manipulacja ciągów znaków i obsługa tablic znaków
  • Arytmetyka znaków ASCII i konwersja typów
  • Arytmetyka modularna i operacje matematyczne
  • Projektowanie funkcji i przekazywanie parametrów
  • Walidacja danych wejściowych i obsługa błędów
  • Struktura programu sterowanego menu
  • Podstawy kryptografii i świadomość bezpieczeństwa

Możliwe Rozszerzenia

Ta podstawowa implementacja może być rozszerzona na różne sposoby:

  • Operacje we/wy plików do szyfrowania/deszyfrowania plików tekstowych
  • Obsługa znaków Unicode i alfabetów międzynarodowych
  • Implementacja innych klasycznych szyfrów (Vigenère, ROT13)
  • Deszyfrowanie brute force dla nieznanych wartości przesunięcia
  • Obsługa argumentów linii poleceń do przetwarzania wsadowego
  • Graficzny interfejs użytkownika używający bibliotek takich jak GTK+

Podsumowanie

Ta implementacja szyfru Cezara w C demonstruje fundamentalne koncepcje programowania, jednocześnie wprowadzając podstawowe zasady kryptograficzne. Kod jest dobrze ustrukturyzowany, zawiera odpowiednią obsługę błędów i zapewnia solidną podstawę do zrozumienia zarówno programowania w C, jak i elementarnych technik szyfrowania. Ćwiczenie z tym przykładem wzmocni Twoje zrozumienie manipulacji ciągów znaków, operacji matematycznych i projektowania programów w C.