Skip to content
IRC-Coding IRC-Coding
Cybersecurity Grundlagen Kryptographie Verschlüsselung Hash Funktionen Digitale Signaturen RSA AES

Cybersecurity Grundlagen: Kryptographie, Verschlüsselung, Hash-Funktionen & Digitale Signaturen

Cybersecurity Grundlagen mit Kryptographie, Verschlüsselung, Hash-Funktionen und digitalen Signaturen. Symmetrische/Asymmetrische Verschlüsselung, RSA, AES, SSL/TLS mit praktischen Beispielen.

S

schutzgeist

2 min read

Cybersecurity Grundlagen: Kryptographie, Verschlüsselung, Hash-Funktionen & Digitale Signaturen

Dieser Beitrag ist eine umfassende Einführung in die Cybersecurity Grundlagen – inklusive Kryptographie, Verschlüsselung, Hash-Funktionen und digitalen Signaturen mit praktischen Beispielen.

In a Nutshell

Kryptographie schützt Daten durch Verschlüsselung, Hash-Funktionen sichern Integrität und digitale Signaturen garantieren Authentizität. Moderne Security basiert auf mathematischen Algorithmen.

Kompakte Fachbeschreibung

Kryptographie ist die Wissenschaft der Verschlüsselung und Entschlüsselung von Informationen zum Schutz vor unbefugtem Zugriff.

Hauptbereiche:

Symmetrische Verschlüsselung

  • Konzept: Gleicher Schlüssel für Ver- und Entschlüsselung
  • Algorithmen: AES, DES, 3DES, Blowfish
  • Vorteile: Schnell, effizient für große Datenmengen
  • Nachteile: Schlüsselverteilung problematisch

Asymmetrische Verschlüsselung

  • Konzept: Öffentlicher und privater Schlüssel
  • Algorithmen: RSA, ECC, DSA, ElGamal
  • Vorteile: Sichere Schlüsselverteilung
  • Nachteile: Langsamer, rechenintensiv

Hash-Funktionen

  • Konzept: Einweg-Funktion für digitale Fingerabdrücke
  • Algorithmen: SHA-256, SHA-3, MD5 (veraltet), bcrypt
  • Eigenschaften: Kollisionsresistenz, Preimage-Resistenz
  • Anwendungen: Passwort-Hashing, Datenintegrität

Digitale Signaturen

  • Konzept: Kryptographische Signatur für Authentizität
  • Prozess: Hashing → Verschlüsseln mit Private Key
  • Verifizierung: Entschlüsseln mit Public Key → Hash-Vergleich
  • Standards: RSA, DSA, ECDSA

Prüfungsrelevante Stichpunkte

  • Kryptographie: Wissenschaft der sicheren Kommunikation
  • Symmetrische Verschlüsselung: AES, gleicher Schlüssel für beide Richtungen
  • Asymmetrische Verschlüsselung: RSA, Public/Private Key-Paare
  • Hash-Funktionen: SHA-256, Einweg-Hash für Integrität
  • Digitale Signaturen: RSA/ECDSA, Authentizität und Integrität
  • SSL/TLS: Verschlüsselte Webkommunikation
  • IHK-relevant: Grundlage für IT-Sicherheit und Datenschutz

Kernkomponenten

  1. Verschlüsselung: Schutz der Vertraulichkeit
  2. Hash-Funktionen: Sicherung der Integrität
  3. Digitale Signaturen: Garantie der Authentizität
  4. Public Key Infrastructure: Schlüsselmanagement
  5. SSL/TLS: Sichere Netzwerkkommunikation
  6. Kryptografische Protokolle: Sichere Datenübertragung
  7. Schlüsselmanagement: Erzeugung, Speicherung, Verteilung
  8. Security Best Practices: Implementierung und Anwendung

Praxisbeispiele

1. Symmetrische Verschlüsselung mit AES

import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.util.Base64;

public class SymmetricEncryptionDemo {
    
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private static final int KEY_LENGTH = 256;
    private static final int IV_LENGTH = 16;
    
    // AES Schlüssel generieren
    public static SecretKey generateAESKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
        keyGenerator.init(KEY_LENGTH);
        return keyGenerator.generateKey();
    }
    
    // Initialisierungsvektor (IV) generieren
    public static byte[] generateIV() {
        byte[] iv = new byte[IV_LENGTH];
        new SecureRandom().nextBytes(iv);
        return iv;
    }
    
    // Daten verschlüsseln
    public static String encryptAES(String plaintext, SecretKey key, byte[] iv) 
            throws Exception {
        
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
        
        byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes());
        
        // IV und verschlüsselte Daten kombinieren
        byte[] combined = new byte[iv.length + encryptedBytes.length];
        System.arraycopy(iv, 0, combined, 0, iv.length);
        System.arraycopy(encryptedBytes, 0, combined, iv.length, encryptedBytes.length);
        
        return Base64.getEncoder().encodeToString(combined);
    }
    
    // Daten entschlüsseln
    public static String decryptAES(String ciphertext, SecretKey key) throws Exception {
        byte[] combined = Base64.getDecoder().decode(ciphertext);
        
        // IV extrahieren
        byte[] iv = new byte[IV_LENGTH];
        System.arraycopy(combined, 0, iv, 0, iv.length);
        
        // Verschlüsselte Daten extrahieren
        byte[] encryptedBytes = new byte[combined.length - iv.length];
        System.arraycopy(combined, iv.length, encryptedBytes, 0, encryptedBytes.length);
        
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
        
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes);
    }
    
    // AES-256 Demo
    public static void aesDemo() {
        try {
            System.out.println("=== AES-256 Verschlüsselung Demo ===");
            
            // Schlüssel generieren
            SecretKey aesKey = generateAESKey();
            System.out.println("AES-256 Schlüssel generiert");
            System.out.println("Schlüssel (Base64): " + Base64.getEncoder().encodeToString(aesKey.getEncoded()));
            
            // Testdaten
            String plaintext = "Dies ist eine geheime Nachricht, die mit AES-256 verschlüsselt wird.";
            System.out.println("\nKlartext: " + plaintext);
            
            // Verschlüsseln
            byte[] iv = generateIV();
            String ciphertext = encryptAES(plaintext, aesKey, iv);
            System.out.println("\nVerschlüsselt: " + ciphertext);
            
            // Entschlüsseln
            String decryptedText = decryptAES(ciphertext, aesKey);
            System.out.println("\nEntschlüsselt: " + decryptedText);
            
            // Überprüfung
            System.out.println("\nVerschlüsselung erfolgreich: " + plaintext.equals(decryptedText));
            
        } catch (Exception e) {
            System.err.println("Fehler bei AES-Verschlüsselung: " + e.getMessage());
        }
    }
    
    // Performance-Vergleich verschiedener AES-Modi
    public static void compareAESModes() {
        try {
            System.out.println("\n=== AES Modi Performance-Vergleich ===");
            
            String[] modes = {"AES/ECB/PKCS5Padding", "AES/CBC/PKCS5Padding", 
                              "AES/GCM/NoPadding", "AES/CFB/PKCS5Padding"};
            
            SecretKey key = generateAESKey();
            String testData = "Performance-Test-Daten für verschiedene AES-Modi. ".repeat(100);
            
            for (String mode : modes) {
                long startTime = System.nanoTime();
                
                try {
                    Cipher cipher = Cipher.getInstance(mode);
                    
                    if (mode.contains("ECB")) {
                        cipher.init(Cipher.ENCRYPT_MODE, key);
                    } else {
                        byte[] iv = generateIV();
                        IvParameterSpec ivSpec = new IvParameterSpec(iv);
                        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
                    }
                    
                    byte[] encrypted = cipher.doFinal(testData.getBytes());
                    
                    long endTime = System.nanoTime();
                    long duration = (endTime - startTime) / 1_000_000; // ms
                    
                    System.out.printf("%-25s: %dms (%d bytes)%n", 
                                     mode, duration, encrypted.length);
                    
                } catch (Exception e) {
                    System.out.printf("%-25s: Fehler - %s%n", mode, e.getMessage());
                }
            }
            
        } catch (Exception e) {
            System.err.println("Fehler bei Performance-Vergleich: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        aesDemo();
        compareAESModes();
    }
}

2. Asymmetrische Verschlüsselung mit RSA

import javax.crypto.*;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;

public class AsymmetricEncryptionDemo {
    
    private static final String ALGORITHM = "RSA";
    private static final int KEY_SIZE = 2048;
    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
    
    // RSA Schlüsselpaar generieren
    public static KeyPair generateRSAKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
        keyGen.initialize(KEY_SIZE);
        return keyGen.generateKeyPair();
    }
    
    // Mit Public Key verschlüsseln
    public static String encryptRSA(String plaintext, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        
        byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
    
    // Mit Private Key entschlüsseln
    public static String decryptRSA(String ciphertext, PrivateKey privateKey) throws Exception {
        byte[] encryptedBytes = Base64.getDecoder().decode(ciphertext);
        
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes);
    }
    
    // Digitale Signatur erstellen
    public static String signData(String data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        
        byte[] signatureBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signatureBytes);
    }
    
    // Digitale Signatur verifizieren
    public static boolean verifySignature(String data, String signatureStr, PublicKey publicKey) 
            throws Exception {
        
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        
        byte[] signatureBytes = Base64.getDecoder().decode(signatureStr);
        return signature.verify(signatureBytes);
    }
    
    // RSA Demo
    public static void rsaDemo() {
        try {
            System.out.println("=== RSA Verschlüsselung Demo ===");
            
            // Schlüsselpaar generieren
            KeyPair keyPair = generateRSAKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();
            
            System.out.println("RSA-2048 Schlüsselpaar generiert");
            System.out.println("Public Key: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
            System.out.println("Private Key: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
            
            // Testdaten
            String plaintext = "Diese Nachricht wird mit RSA-2048 verschlüsselt und digital signiert.";
            System.out.println("\nKlartext: " + plaintext);
            
            // Verschlüsseln mit Public Key
            String ciphertext = encryptRSA(plaintext, publicKey);
            System.out.println("\nVerschlüsselt (Public Key): " + ciphertext);
            
            // Entschlüsseln mit Private Key
            String decryptedText = decryptRSA(ciphertext, privateKey);
            System.out.println("Entschlüsselt (Private Key): " + decryptedText);
            
            // Digitale Signatur erstellen
            String signature = signData(plaintext, privateKey);
            System.out.println("\nDigitale Signatur: " + signature);
            
            // Signatur verifizieren
            boolean isValid = verifySignature(plaintext, signature, publicKey);
            System.out.println("Signatur gültig: " + isValid);
            
            // Manipulierte Signatur testen
            String manipulatedData = plaintext + " (manipuliert)";
            boolean isManipulatedValid = verifySignature(manipulatedData, signature, publicKey);
            System.out.println("Manipulierte Signatur gültig: " + isManipulatedValid);
            
        } catch (Exception e) {
            System.err.println("Fehler bei RSA-Verschlüsselung: " + e.getMessage());
        }
    }
    
    // Hybrid-Verschlüsselung (RSA + AES)
    public static void hybridEncryptionDemo() {
        try {
            System.out.println("\n=== Hybrid-Verschlüsselung Demo (RSA + AES) ===");
            
            // Schlüssel generieren
            KeyPair rsaKeyPair = generateRSAKeyPair();
            SecretKey aesKey = SymmetricEncryptionDemo.generateAESKey();
            
            // Große Datenmenge
            String largeData = "Dies ist eine große Datenmenge, die mit AES verschlüsselt und der AES-Schlüssel dann mit RSA verschlüsselt wird. ".repeat(50);
            System.out.println("Originaldaten Größe: " + largeData.length() + " Zeichen");
            
            // Schritt 1: Daten mit AES verschlüsseln
            byte[] iv = SymmetricEncryptionDemo.generateIV();
            String encryptedData = SymmetricEncryptionDemo.encryptAES(largeData, aesKey, iv);
            System.out.println("Mit AES verschlüsselt: " + encryptedData.length() + " Zeichen");
            
            // Schritt 2: AES-Schlüssel mit RSA verschlüsseln
            String encryptedKey = encryptRSA(Base64.getEncoder().encodeToString(aesKey.getEncoded()), rsaKeyPair.getPublic());
            System.out.println("AES-Schlüssel mit RSA verschlüsselt");
            
            // Schritt 3: Entschlüsselung (umgekehrt)
            String decryptedKey = decryptRSA(encryptedKey, rsaKeyPair.getPrivate());
            byte[] decodedKey = Base64.getDecoder().decode(decryptedKey);
            SecretKey restoredAESKey = new SecretKeySpec(decodedKey, "AES");
            
            String decryptedData = SymmetricEncryptionDemo.decryptAES(encryptedData, restoredAESKey);
            
            System.out.println("Hybrid-Verschlüsselung erfolgreich: " + largeData.equals(decryptedData));
            
        } catch (Exception e) {
            System.err.println("Fehler bei Hybrid-Verschlüsselung: " + e.getMessage());
        }
    }
    
    // RSA Key-Size Vergleich
    public static void compareKeySizes() {
        try {
            System.out.println("\n=== RSA Key-Size Vergleich ===");
            
            int[] keySizes = {1024, 2048, 4096};
            String testData = "Testdaten für Key-Size Vergleich";
            
            for (int keySize : keySizes) {
                try {
                    KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
                    keyGen.initialize(keySize);
                    KeyPair keyPair = keyGen.generateKeyPair();
                    
                    long startTime = System.nanoTime();
                    String encrypted = encryptRSA(testData, keyPair.getPublic());
                    long encryptTime = System.nanoTime() - startTime;
                    
                    startTime = System.nanoTime();
                    String decrypted = decryptRSA(encrypted, keyPair.getPrivate());
                    long decryptTime = System.nanoTime() - startTime;
                    
                    System.out.printf("RSA-%d: Verschlüsselung %dms, Entschlüsselung %dms%n",
                                     keySize, encryptTime / 1_000_000, decryptTime / 1_000_000);
                    
                } catch (Exception e) {
                    System.out.printf("RSA-%d: Fehler - %s%n", keySize, e.getMessage());
                }
            }
            
        } catch (Exception e) {
            System.err.println("Fehler bei Key-Size Vergleich: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        rsaDemo();
        hybridEncryptionDemo();
        compareKeySizes();
    }
}

3. Hash-Funktionen und Passwort-Sicherheit

import java.security.*;
import java.util.Base64;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.Arrays;

public class HashFunctionsDemo {
    
    private static final String SHA_256 = "SHA-256";
    private static final String SHA_3_256 = "SHA3-256";
    private static final String BCRYPT = "BCrypt";
    
    // SHA-256 Hash berechnen
    public static String sha256(String input) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance(SHA_256);
        byte[] hashBytes = digest.digest(input.getBytes());
        return Base64.getEncoder().encodeToString(hashBytes);
    }
    
    // SHA-3 Hash berechnen
    public static String sha3_256(String input) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance(SHA_3_256);
        byte[] hashBytes = digest.digest(input.getBytes());
        return Base64.getEncoder().encodeToString(hashBytes);
    }
    
    // Salted Hash (mit zufälligem Salt)
    public static String saltedHash(String password, byte[] salt) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance(SHA_256);
        digest.reset();
        digest.update(salt);
        byte[] hashBytes = digest.digest(password.getBytes());
        return Base64.getEncoder().encodeToString(hashBytes);
    }
    
    // Salt generieren
    public static byte[] generateSalt() {
        byte[] salt = new byte[16];
        new SecureRandom().nextBytes(salt);
        return salt;
    }
    
    // PBKDF2 für Passwort-Hashing
    public static String pbkdf2Hash(String password, byte[] salt, int iterations, int keyLength) 
            throws NoSuchAlgorithmException, InvalidKeySpecException {
        
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, keyLength);
        SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        byte[] hash = skf.generateSecret(spec).getEncoded();
        return Base64.getEncoder().encodeToString(hash);
    }
    
    // Passwort mit PBKDF2 verifizieren
    public static boolean verifyPassword(String password, String storedHash, byte[] salt, int iterations) 
            throws NoSuchAlgorithmException, InvalidKeySpecException {
        
        String newHash = pbkdf2Hash(password, salt, iterations, storedHash.length());
        return newHash.equals(storedHash);
    }
    
    // HMAC für Message Authentication
    public static String hmacSHA256(String data, String secretKey) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
        mac.init(secretKeySpec);
        byte[] hmacBytes = mac.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(hmacBytes);
    }
    
    // Hash-Kollisionstest
    public static void testHashCollisions() {
        try {
            System.out.println("=== Hash-Kollisionstest ===");
            
            String[] testStrings = {
                "password123",
                "password124",  // Sehr ähnlich
                "Password123",  // Groß/Kleinschreibung
                "pass word123", // Leerzeichen
                "pa$$word123"   // Sonderzeichen
            };
            
            System.out.println("SHA-256 Hashes:");
            for (String test : testStrings) {
                String hash = sha256(test);
                System.out.printf("%-15s: %s%n", test, hash);
            }
            
            System.out.println("\nSHA-3 Hashes:");
            for (String test : testStrings) {
                String hash = sha3_256(test);
                System.out.printf("%-15s: %s%n", test, hash);
            }
            
        } catch (Exception e) {
            System.err.println("Fehler bei Kollisionstest: " + e.getMessage());
        }
    }
    
    // Passwort-Sicherheits-Demo
    public static void passwordSecurityDemo() {
        try {
            System.out.println("\n=== Passwort-Sicherheits-Demo ===");
            
            String password = "MySecurePassword123!";
            
            // 1. Einfacher Hash (unsicher)
            String simpleHash = sha256(password);
            System.out.println("Einfacher SHA-256: " + simpleHash);
            
            // 2. Salted Hash
            byte[] salt = generateSalt();
            String saltedHashStr = saltedHash(password, salt);
            System.out.println("Salted Hash: " + saltedHashStr);
            System.out.println("Salt: " + Base64.getEncoder().encodeToString(salt));
            
            // 3. PBKDF2 (empfohlen)
            int iterations = 10000;
            int keyLength = 256;
            String pbkdf2HashStr = pbkdf2Hash(password, salt, iterations, keyLength);
            System.out.println("PBKDF2 Hash: " + pbkdf2HashStr);
            System.out.println("Iterationen: " + iterations);
            
            // 4. Verifikation
            boolean isValid = verifyPassword(password, pbkdf2HashStr, salt, iterations);
            System.out.println("Passwort gültig: " + isValid);
            
            // 5. Timing Attack Protection
            System.out.println("\nTiming Attack Protection Test:");
            testTimingAttackProtection();
            
        } catch (Exception e) {
            System.err.println("Fehler bei Passwort-Sicherheit: " + e.getMessage());
        }
    }
    
    // Timing Attack Protection Demo
    public static void testTimingAttackProtection() {
        try {
            String correctPassword = "correctPassword123";
            String wrongPassword = "wrongPassword456";
            
            byte[] salt = generateSalt();
            String storedHash = pbkdf2Hash(correctPassword, salt, 10000, 256);
            
            // Timing Tests
            long[] correctTimes = new long[10];
            long[] wrongTimes = new long[10];
            
            for (int i = 0; i < 10; i++) {
                // Korrektes Passwort
                long start = System.nanoTime();
                verifyPassword(correctPassword, storedHash, salt, 10000);
                correctTimes[i] = System.nanoTime() - start;
                
                // Falsches Passwort
                start = System.nanoTime();
                verifyPassword(wrongPassword, storedHash, salt, 10000);
                wrongTimes[i] = System.nanoTime() - start;
            }
            
            long avgCorrect = Arrays.stream(correctTimes).sum() / correctTimes.length;
            long avgWrong = Arrays.stream(wrongTimes).sum() / wrongTimes.length;
            
            System.out.printf("Korrektes Passwort: %dms (Durchschnitt)%n", avgCorrect / 1_000_000);
            System.out.printf("Falsches Passwort: %dms (Durchschnitt)%n", avgWrong / 1_000_000);
            System.out.printf("Timing-Differenz: %.2f%%n", 
                             Math.abs(avgCorrect - avgWrong) * 100.0 / Math.max(avgCorrect, avgWrong));
            
        } catch (Exception e) {
            System.err.println("Fehler bei Timing Attack Test: " + e.getMessage());
        }
    }
    
    // HMAC Demo
    public static void hmacDemo() {
        try {
            System.out.println("\n=== HMAC Demo ===");
            
            String message = "Dies ist eine vertrauliche Nachricht";
            String secretKey = "geheimerSchlüssel123";
            
            // HMAC berechnen
            String hmac = hmacSHA256(message, secretKey);
            System.out.println("Nachricht: " + message);
            System.out.println("HMAC: " + hmac);
            
            // HMAC mit falschem Schlüssel
            String wrongKey = "falscherSchlüssel456";
            String wrongHmac = hmacSHA256(message, wrongKey);
            System.out.println("HMAC (falscher Key): " + wrongHmac);
            
            // Verifikation
            boolean isValid = hmac.equals(hmacSHA256(message, secretKey));
            boolean isInvalid = !wrongHmac.equals(hmacSHA256(message, secretKey));
            
            System.out.println("HMAC gültig: " + isValid);
            System.out.println("Falscher HMAC erkannt: " + isInvalid);
            
        } catch (Exception e) {
            System.err.println("Fehler bei HMAC Demo: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        testHashCollisions();
        passwordSecurityDemo();
        hmacDemo();
    }
}

4. SSL/TLS und Zertifikate

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.security.*;
import java.security.cert.*;
import java.util.Base64;

public class SSLTLSDemo {
    
    // SSL-Kontext erstellen
    public static SSLContext createSSLContext() throws Exception {
        // Trust Manager (für Server-Zertifikate)
        TrustManager[] trustManagers = new TrustManager[] {
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                
                public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                }
                
                public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                // In Produktion: Zertifikat validieren
                    System.out.println("Server-Zertifikat validiert");
                }
            }
        };
        
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustManagers, new SecureRandom());
        
        return sslContext;
    }
    
    // HTTPS-Request mit SSL
    public static void makeHTTPSRequest(String urlString) {
        try {
            System.out.println("=== HTTPS Request Demo ===");
            
            URL url = new URL(urlString);
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            
            // SSL-Kontext setzen
            SSLContext sslContext = createSSLContext();
            connection.setSSLSocketFactory(sslContext.getSocketFactory());
            
            // Hostname Verifier (für Demo)
            connection.setHostnameVerifier((hostname, session) -> {
                System.out.println("Hostname: " + hostname);
                return true; // In Produktion: proper hostname verification
            });
            
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(10000);
            
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);
            
            // Zertifikatsinformationen
            Certificate[] certs = connection.getServerCertificates();
            if (certs.length > 0 && certs[0] instanceof java.security.cert.X509Certificate) {
                java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate) certs[0];
                System.out.println("Server-Zertifikat:");
                System.out.println("  Subject: " + cert.getSubjectDN());
                System.out.println("  Issuer: " + cert.getIssuerDN());
                System.out.println("  Valid from: " + cert.getNotBefore());
                System.out.println("  Valid until: " + cert.getNotAfter());
                System.out.println("  Serial Number: " + cert.getSerialNumber());
            }
            
            // TLS-Version
            System.out.println("TLS Protocol: " + connection.getSSLSession().getProtocol());
            System.out.println("Cipher Suite: " + connection.getSSLSession().getCipherSuite());
            
            // Antwort lesen
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(connection.getInputStream()))) {
                
                String line;
                StringBuilder response = new StringBuilder();
                
                while ((line = reader.readLine()) != null) {
                    response.append(line).append("\n");
                }
                
                System.out.println("Response (first 200 chars):");
                System.out.println(response.substring(0, Math.min(200, response.length())));
            }
            
        } catch (Exception e) {
            System.err.println("Fehler bei HTTPS Request: " + e.getMessage());
        }
    }
    
    // Selbstsigniertes Zertifikat erstellen
    public static void generateSelfSignedCertificate() {
        try {
            System.out.println("\n=== Selbstsigniertes Zertifikat Demo ===");
            
            // KeyPair generieren
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            keyGen.initialize(2048);
            KeyPair keyPair = keyGen.generateKeyPair();
            
            // Zertifikat erstellen (vereinfacht)
            // In der Praxis würde man BouncyCastle oder ähnliche Libraries verwenden
            System.out.println("KeyPair generiert für selbstsigniertes Zertifikat");
            System.out.println("Public Key: " + Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()));
            
        } catch (Exception e) {
            System.err.println("Fehler bei Zertifikatserstellung: " + e.getMessage());
        }
    }
    
    // Cipher Suites auflisten
    public static void listCipherSuites() {
        try {
            System.out.println("\n=== Unterstützte Cipher Suites ===");
            
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, null, null);
            
            String[] cipherSuites = sslContext.getServerSocketFactory().getSupportedCipherSuites();
            
            System.out.println("Anzahl unterstützter Cipher Suites: " + cipherSuites.length);
            System.out.println("\nEmpfohlene Cipher Suites:");
            
            for (String suite : cipherSuites) {
                // Nur moderne, sichere Cipher Suites anzeigen
                if (suite.contains("TLS_ECDHE") && suite.contains("GCM")) {
                    System.out.println("  " + suite);
                }
            }
            
        } catch (Exception e) {
            System.err.println("Fehler bei Cipher Suite Auflistung: " + e.getMessage());
        }
    }
    
    // SSL-Handshake analysieren
    public static void analyzeSSLHandshake() {
        try {
            System.out.println("\n=== SSL Handshake Analyse ===");
            
            SSLContext sslContext = createSSLContext();
            
            // Custom SSL Parameters
            SSLParameters sslParams = new SSLParameters();
            sslParams.setEndpointIdentificationAlgorithm("HTTPS");
            sslParams.setProtocols(new String[]{"TLSv1.3", "TLSv1.2"});
            
            // Sichere Cipher Suites
            String[] secureSuites = {
                "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
                "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
                "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
            };
            sslParams.setCipherSuites(secureSuites);
            
            System.out.println("SSL Konfiguration:");
            System.out.println("  Protokolle: " + String.join(", ", sslParams.getProtocols()));
            System.out.println("  Cipher Suites: " + sslParams.getCipherSuites().length + " konfiguriert");
            System.out.println("  Hostname Verification: " + sslParams.getEndpointIdentificationAlgorithm());
            
        } catch (Exception e) {
            System.err.println("Fehler bei SSL Analyse: " + e.getMessage());
        }
    }
    
    // Certificate Chain Validation
    public static void validateCertificateChain() {
        try {
            System.out.println("\n=== Certificate Chain Validation ===");
            
            // Beispiel für Certificate Path Validation
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            
            // In der Praxis würde man die Zertifikate aus einer Datei laden
            // Hier zeigen wir nur die Konzepte
            
            System.out.println("Certificate Path Validation Konzepte:");
            System.out.println("1. Root CA Certificate");
            System.out.println("2. Intermediate CA Certificate(s)");
            System.out.println("3. End Entity Certificate");
            System.out.println("4. Certificate Revocation Check (CRL/OCSP)");
            System.out.println("5. Certificate Transparency Logs");
            
            // Trust Manager Konfiguration
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            
            // KeyStore für vertrauenswürdige Zertifikate
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null); // Leerer TrustStore
            
            // In Produktion: System-TrustStore laden oder eigene Zertifikate hinzufügen
            // trustStore.load(new FileInputStream("truststore.jks"), "password".toCharArray());
            
            tmf.init(trustStore);
            
            TrustManager[] trustManagers = tmf.getTrustManagers();
            System.out.println("Trust Manager konfiguriert: " + trustManagers.length + " Manager");
            
        } catch (Exception e) {
            System.err.println("Fehler bei Certificate Validation: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) {
        // HTTPS Request Demo
        // makeHTTPSRequest("https://www.google.com");
        
        // Zertifikat-Demos
        generateSelfSignedCertificate();
        listCipherSuites();
        analyzeSSLHandshake();
        validateCertificateChain();
    }
}

Kryptographie-Algorithmen Übersicht

Symmetrische Algorithmen

AlgorithmusSchlüssellängeBlockgrößeAnwendungSicherheit
AES128/192/256128 BitStandardSicher
DES5664VeraltetUnsicher
3DES16864LegacySchwach
Blowfish32-44864VerschiedeneSicher

Asymmetrische Algorithmen

AlgorithmusSchlüssellängeAnwendungSicherheitPerformance
RSA1024-4096Signatur/VerschlüsselungSicherLangsam
ECC160-521Signatur/VerschlüsselungSicherSchnell
DSA1024-3072SignaturSicherLangsam
ElGamal1024-4096VerschlüsselungSicherLangsam

Hash-Algorithmen

AlgorithmusAusgabelängeKollisionssicherheitStatusAnwendung
SHA-256256 BitSicherEmpfohlenAllzweck
SHA-3224-512SicherModernAllzweck
MD5128 BitGebrochenVeraltetPrüfsummen
bcryptVariableSicherEmpfohlenPasswörter

SSL/TLS Protokoll-Versionen

VersionJahrSicherheitCipher SuitesEmpfehlung
SSL 2.01995UnsicherVeraltetNicht verwenden
SSL 3.01996UnsicherVeraltetNicht verwenden
TLS 1.01999SchwachBegrenztNicht verwenden
TLS 1.12006OKBegrenztNicht verwenden
TLS 1.22008SicherModernEmpfohlen
TLS 1.32018Sehr SicherModernBeste Wahl

Passwort-Sicherheit Best Practices

Hashing-Methoden

// ❌ Unsicher
String hash = md5(password);

// ⚠️ Besser
String hash = sha256(password);

// ✅ Sicher
String hash = pbkdf2(password, salt, 100000);

// ✅ Am besten
String hash = bcrypt(password);

Salting

// Salt generieren
byte[] salt = generateSalt(); // 16+ Bytes zufällig

// Salt speichern (nicht geheim)
String saltedHash = salt + ":" + hash(password, salt);

Key Derivation

// PBKDF2 Parameter
int iterations = 100000; // Mindestens 100.000
int keyLength = 256;     // 256 Bit
int saltLength = 32;     // 32 Bytes

String derivedKey = pbkdf2(password, salt, iterations, keyLength);

Digitale Signaturen Prozess

Signatur-Erstellung

  1. Hash berechnen: hash = SHA256(data)
  2. Hash verschlüsseln: signature = RSA_encrypt(hash, private_key)
  3. Signatur anhängen: data + signature

Signatur-Verifizierung

  1. Signatur extrahieren: signature = extract(data_with_signature)
  2. Hash berechnen: hash = SHA256(data)
  3. Signatur entschlüsseln: decrypted_hash = RSA_decrypt(signature, public_key)
  4. Vergleichen: hash == decrypted_hash ?

Public Key Infrastructure (PKI)

Komponenten

  • Root CA: Vertrauenswürdige Stammzertifizierungsstelle
  • Intermediate CA: Zwischenzertifizierungsstellen
  • End Entity: Server/Client-Zertifikate
  • CRL: Certificate Revocation List
  • OCSP: Online Certificate Status Protocol

Zertifikats-Validierung

// 1. Certificate Chain prüfen
// 2. Ablaufdatum prüfen
// 3. Revocation prüfen (CRL/OCSP)
// 4. Hostname prüfen
// 5. Signatur prüfen

Security Best Practices

Implementation

// ✅ Sichere Konfiguration
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(null, trustManagers, null);

// ✅ Sichere Cipher Suites
String[] secureSuites = {
    "TLS_AES_256_GCM_SHA384",
    "TLS_CHACHA20_POLY1305_SHA256",
    "TLS_AES_128_GCM_SHA256"
};

// ✅ Hostname Verification
connection.setHostnameVerifier((hostname, session) -> {
    return hostname.equals(session.getPeerHost());
});

Fehlervermeidung

// ❌ Falsch: TrustManager deaktivieren
TrustManager[] trustAllCerts = new TrustManager[] {
    new X509TrustManager() { /* alle Zertifikate akzeptieren */ }
};

// ✅ Richtig: Eigene TrustManager mit Validierung
TrustManager[] secureTrustManagers = new TrustManager[] {
    new X509TrustManager() {
        public void checkServerTrusted(X509Certificate[] chain, String authType) 
                throws CertificateException {
            // Eigene Validierungslogik
        }
    }
};

Vorteile und Nachteile

Vorteile von Kryptographie

  • Vertraulichkeit: Schutz vor unbefugtem Zugriff
  • Integrität: Erkennung von Datenmanipulation
  • Authentizität: Verifizierung der Identität
  • Non-Repudiation: Nichtanfechtbarkeit
  • Compliance: Erfüllung von Sicherheitsstandards

Nachteile

  • Komplexität: Fachwissen erforderlich
  • Performance: Rechenintensive Operationen
  • Key Management: Schlüsselverwaltung aufwändig
  • Overhead: Zusätzliche Infrastruktur

Häufige Prüfungsfragen

  1. Was ist der Unterschied zwischen symmetrischer und asymmetrischer Verschlüsselung? Symmetrisch verwendet einen Schlüssel für beide Richtungen, asymmetrisch verwendet Public/Private Key-Paare.

  2. Warum sind Salted Hashes für Passwörter wichtig? Salts verhindern Rainbow-Table-Angriffe und sorgen für einzigartige Hashes auch bei gleichen Passwörtern.

  3. Erklären Sie digitale Signaturen! Digitale Signaturen verwenden Hashing und asymmetrische Verschlüsselung um Authentizität und Integrität zu garantieren.

  4. Was ist der Zweck von SSL/TLS? SSL/TLS sichert die Kommunikation im Internet durch Verschlüsselung und Authentifizierung.

Wichtigste Quellen

  1. https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html
  2. https://www.ietf.org/rfc/rfc5246.html (TLS 1.2)
  3. https://www.ietf.org/rfc/rfc8446.html (TLS 1.3)
Zurück zum Blog
Share: