Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

Affine-Chiffre mit Android Studio: SDPEncryptor-Tutorial für CS6601 (Herbst 2025)

Lerne, wie du eine einfache Affine-Chiffre in einer Android-App implementierst. Dieses Tutorial begleitet dich durch die Einrichtung von Android Studio, die Fehlerbehandlung mit EditText.setError() und die Umsetzung der Verschlüsselungslogik – inspiriert von modernen Messaging-Apps und Datenschutz-T

Affine-Chiffre Android Studio SDPEncryptor Tutorial CS6601 Assignment 4 Lösung Android App Verschlüsselung EditText setError Beispiel Affine Cipher Java Android Android Studio Projekt einrichten Fehlerbehandlung Android App Unit Tests Robolectric Android Datenschutz App Entwicklung Verschlüsselung für Anfänger Mobile Security Studium Android API 34 Tutorial Affine Transformation Programmierung SDPEncryptor Fall 2025 CS6601 Herbst 2025

Einführung in die Affine-Chiffre und SDPEncryptor

Im Rahmen der CS6601 Assignment 4 (Herbst 2025) entwickelst du eine Android-App namens SDPEncryptor, die Nachrichten mit einer Affine-Chiffre verschlüsselt. Die Affine-Chiffre ist eine klassische monoalphabetische Substitutionschiffre, die auf einer linearen Transformation basiert: E(x) = (a * x + b) mod m, wobei a und m teilerfremd sein müssen. In Zeiten von Datenschutz und Ende-zu-Ende-Verschlüsselung (z. B. in WhatsApp, Signal) ist das Verständnis grundlegender Verschlüsselungsmechanismen relevanter denn je. Dieses Tutorial führt dich Schritt für Schritt durch die Implementierung.

Projekt einrichten: Android Studio und Build-Konfiguration

Die Einrichtung der Entwicklungsumgebung ist ein zentrales Lernziel. Verwende Android Studio Ladybug Feature Drop | 2024.2.2 (oder aktuell). Lege ein neues Projekt mit folgenden Parametern an:

  • Package-Name: edu.gatech.seclass.sdpencryptor
  • Sprache: Java (Kotlin optional, aber Java wird bevorzugt unterstützt)
  • Minimum SDK: API 34 (Android 14)
  • Build-Konfiguration: Groovy DSL (build.gradle)

Passe die build.gradle (Module: app) wie folgt an:

android {
    compileSdk 34
    defaultConfig {
        minSdk 34
        targetSdk 34
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    testOptions {
        unitTests {
            includeAndroidResources true
        }
    }
    lintOptions {
        tasks.lint.enabled = false
        abortOnError false
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.robolectric:robolectric:4.11.1'
}

Stelle sicher, dass die compileSdk und targetSdk auf 34 gesetzt sind. Die Abhängigkeiten entsprechen den Vorgaben. Vergiss nicht, nach dem Ändern der Gradle-Dateien auf Sync Now zu klicken.

UI-Layout mit den erforderlichen Widget-IDs

Erstelle ein Layout mit den folgenden Widgets und IDs. Die genauen IDs sind für die automatische Bewertung zwingend erforderlich:

  • EditText für die Eingabe des Klartextes: @+id/plainText
  • EditText für den Schlüsselparameter a: @+id/keyA
  • EditText für den Schlüsselparameter b: @+id/keyB
  • Button zum Verschlüsseln: @+id/encryptButton
  • TextView für das verschlüsselte Ergebnis: @+id/encryptedText

Ein mögliches Layout (vereinfacht):

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/plainText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Klartext eingeben"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <EditText
        android:id="@+id/keyA"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Schlüssel a"
        android:inputType="number"
        app:layout_constraintTop_toBottomOf="@id/plainText"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/keyB" />

    <EditText
        android:id="@+id/keyB"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Schlüssel b"
        android:inputType="number"
        app:layout_constraintTop_toBottomOf="@id/plainText"
        app:layout_constraintLeft_toRightOf="@id/keyA"
        app:layout_constraintRight_toRightOf="parent" />

    <Button
        android:id="@+id/encryptButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Verschlüsseln"
        app:layout_constraintTop_toBottomOf="@id/keyA"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/encryptedText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text=""
        android:padding="16dp"
        app:layout_constraintTop_toBottomOf="@id/encryptButton"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Beachte: Die genauen Abstände und Anordnung sind dir überlassen, aber die IDs müssen exakt stimmen.

Fehlerbehandlung mit EditText.setError()

Ein zentrales Feature der App ist die Fehlerbehandlung. Wenn der Benutzer auf den Button drückt, müssen drei Fehlerfälle abgefangen werden:

  1. Leeres Klartextfeld: Zeige einen Fehler auf dem plainText-Feld an.
  2. Ungültiger Schlüssel a: a muss eine positive ganze Zahl sein und teilerfremd zu 26 (Anzahl der Buchstaben).
  3. Ungültiger Schlüssel b: b muss eine nicht-negative ganze Zahl sein.

Verwende die Methode setError(String) des EditText-Widgets. Beispiel:

if (plainText.getText().toString().isEmpty()) {
    plainText.setError("Klartext darf nicht leer sein");
} else {
    plainText.setError(null);
}

Rufe diese Prüfungen im OnClickListener des Buttons auf. Mehrere Fehler können gleichzeitig aktiv sein – das wird durch die aufgerufenen setError-Aufrufe erreicht.

Implementierung der Affine-Chiffre

Die Affine-Chiffre arbeitet auf Buchstaben A-Z (Großbuchstaben). Kleinbuchstaben werden ignoriert oder in Großbuchstaben umgewandelt. Die Verschlüsselungsformel lautet:

c = (a * p + b) mod 26

wobei p die Position des Klartextbuchstabens (A=0, B=1, ..., Z=25) und c die Position des Geheimtextbuchstabens ist. Für die Entschlüsselung wird der modulare Kehrwert von a modulo 26 benötigt. In dieser Aufgabe reicht die Verschlüsselung.

Beispiel: Mit a=5, b=8 und Klartext „HELLO“ ergibt sich:

  • H (7) → (5*7+8)=43 mod 26 = 17 → R
  • E (4) → (5*4+8)=28 mod 26 = 2 → C
  • L (11) → (5*11+8)=63 mod 26 = 11 → L
  • L (11) → 11 → L
  • O (14) → (5*14+8)=78 mod 26 = 0 → A

Ergebnis: „RCLLA“.

Implementiere eine Methode String encrypt(String plainText, int a, int b), die diese Transformation durchführt. Ignoriere Zeichen, die keine Buchstaben sind, oder wirf einen Fehler – je nach Vorgabe deines Dozenten.

Unit-Tests mit JUnit und Robolectric

Die Assignment-Vorgabe schreibt vor, dass du Unit-Tests mit JUnit 4.13.2 und Robolectric 4.11.1 schreibst. Robolectric ermöglicht es, Android-Komponenten ohne Emulator zu testen. Ein einfacher Test für die Verschlüsselungsfunktion könnte so aussehen:

import org.junit.Test;
import static org.junit.Assert.*;

public class EncryptorTest {
    @Test
    public void testEncrypt() {
        Encryptor encryptor = new Encryptor();
        String result = encryptor.encrypt("HELLO", 5, 8);
        assertEquals("RCLLA", result);
    }
}

Für UI-Tests mit Robolectric erstellst du eine Aktivität und prüfst die Fehleranzeige:

@RunWith(RobolectricTestRunner.class)
public class MainActivityTest {
    @Test
    public void testEmptyPlainTextError() {
        ActivityController<MainActivity> controller = Robolectric.buildActivity(MainActivity.class);
        controller.setup();
        MainActivity activity = controller.get();
        Button button = activity.findViewById(R.id.encryptButton);
        button.performClick();
        EditText plainText = activity.findViewById(R.id.plainText);
        assertNotNull(plainText.getError());
    }
}

Stelle sicher, dass du die Testkonfiguration in der build.gradle wie oben angegeben aktiviert hast.

Häufige Fehler und Tipps

Einige typische Stolpersteine:

  • Falsche Package-Struktur: Das Hauptpaket muss edu.gatech.seclass.sdpencryptor heißen.
  • Vergessene Ressourcen-IDs: Die IDs müssen exakt mit den Vorgaben übereinstimmen, sonst erkennt der Autograder die Widgets nicht.
  • Fehler bei der Build-Konfiguration: Achte auf die exakte Version der Abhängigkeiten. Verwende keine neueren Versionen, da sie zu Inkompatibilitäten führen können.
  • Keine Fehlerbehandlung bei leerem Text: Der Autograder erwartet, dass setError aufgerufen wird. Teste auch den Fall, dass beide Schlüssel ungültig sind.

Zusammenfassung und Ausblick

Mit diesem Tutorial hast du die Grundlagen für die CS6601 Assignment 4 gelegt. Du hast gelernt, wie man ein Android-Projekt mit den richtigen Einstellungen konfiguriert, eine affine Chiffre implementiert und Fehler mit EditText.setError() behandelt. Diese Fähigkeiten sind nicht nur für die Abgabe wichtig, sondern auch für das spätere Gruppenprojekt. In einer Zeit, in der Datenschutz und sichere Kommunikation immer wichtiger werden – sei es in Messaging-Apps oder bei der Verschlüsselung von Benutzerdaten – ist das Verständnis solcher Algorithmen ein wertvolles Werkzeug. Viel Erfolg bei deiner Implementierung!