Fachlicher Vertrag: unverändert zu erhalten
- Neue Verschlüsselung bietet Vertraulichkeit und Integrität.
- Nonce/IV wird pro Nachricht eindeutig erzeugt.
- Schlüsselmaterial und Passwörter werden nicht geloggt oder hart codiert.
deterministische AES-ECB-Demo wird nachvollziehbar in AES-GCM mit PBKDF2, Salt und IV überführt. Die Akte zeigt nicht nur das Ziel, sondern die tatsächlichen Dateien, APIs, Dependencies, Codebelege, Tests, Risiken und Cutover-Schritte.
| Dimension | Legacy | Modern | Migrationskonsequenz |
|---|---|---|---|
| Programmiermodell | imperativ / ohne Framework-Annotationen | explizite Java-Abstraktionen | Annotationen und Containerfunktionen werden nur dort eingesetzt, wo sie eine konkrete technische Verantwortung übernehmen. |
| Abhängigkeiten | 1 direkte Dependencies | 1 direkte Dependencies | 0 neu, 0 entfernt; Versionen und transitive Auswirkungen im erfolgreichen Online-Build prüfen. |
| Öffentliche API | 2 erkannte Methoden | 5 erkannte Methoden | Methoden werden nach fachlicher Rolle gemappt; reine Bootstrap- und Framework-Methoden sind kein fachlicher Vertrag. |
| Datenmodell | class LegacyAesEcb | class AesGcmService, record EncryptedPayload | Feldnamen, IDs, Null-Semantik, Gleichheit und Serialisierungsform werden separat regressionstestet. |
| Fehlerverhalten | Legacy-Exceptions und Rückgabewerte | explizitere Fach-/Framework-Fehlerabbildung | Fehler dürfen nicht nur technisch übersetzt werden; Status, Ursache, Retrybarkeit und Client-Vertrag müssen erhalten oder versioniert werden. |
| Tests | Bestands- und Golden-Master-Tests | Unit-, Slice-, Contract- und Integrationstests | Der Modern-Pfad wird zuerst gegen denselben fachlichen Vektor geprüft und danach um neue technische Risiken ergänzt. |
| Betrieb | Legacy-Start/Lifecycle | modernes Packaging, Health und externe Konfiguration | Kein Rollback auf unsichere Schreibverfahren; Migration von Bestandsdaten kontrollieren. |
| Rollback | Legacy-Artefakt bleibt unverändert | Modern-Artefakt getrennt deploybar | Kein Rollback über Datenverlust: Schema, Nachrichten und verschlüsselte Daten müssen rückwärtslesbar oder durch Dual-Read abgesichert sein. |
confidentiality/integrity failure and nonce misuse
tamper, wrong key, nonce uniqueness and empty payload tests
Die Zuordnung ist semantisch: Eine Legacy-Klasse kann in mehrere moderne Rollen zerlegt werden.
| Legacy-Rolle / Datei | Modern-Rolle / Datei | Bedeutung |
|---|---|---|
| LegacyAesEcb.java | AesGcmService.java + EncryptedPayload.java | Deterministische Verschlüsselung wird authentifizierte, versionierbare Payload. |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| LegacyAesEcb.java | class LegacyAesEcb | — | String encrypt(String text, String password) String decrypt(String value, String password) | Security Gateway (Legacy-Antipattern) – bündelt Kryptografie, verwendet absichtlich unsicheres ECB. | 28 |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| AesGcmService.java | class AesGcmService | — | EncryptedPayload encrypt(String text, char[] password) String decrypt(EncryptedPayload p, char[] password) | Security Gateway | 31 |
| EncryptedPayload.java | record EncryptedPayload | — | byte[] salt() byte[] iv() byte[] cipherText() | Value Object | 23 |
| Status | Dependency | Version | Scope | Prüfung |
|---|---|---|---|---|
| BEIBEHALTEN | org.junit.jupiter:junit-jupiter | BOM/Parent → BOM/Parent | test → test | Gemeinsame Dependency; Version und Scope im effektiven POM prüfen. |
Die folgenden Ausschnitte stammen direkt aus den enthaltenen Projekten. Dadurch ist sichtbar, welche Verantwortung tatsächlich verschoben wurde.
Migrationsbedeutung: Deterministische Verschlüsselung wird authentifizierte, versionierbare Payload.
projects/32-crypto/legacy/src/main/java/at/aydin/lab/crypto/legacy/LegacyAesEcb.java
package at.aydin.lab.crypto.legacy;
// Design Pattern: Security Gateway (Legacy-Antipattern) – bündelt Kryptografie, verwendet absichtlich unsicheres ECB.
import javax.crypto.*;
import javax.crypto.spec.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.*;
/** Lern-Antipattern: AES/ECB ist deterministisch und für produktive Daten ungeeignet. */
public final class LegacyAesEcb {
private SecretKey key(String password) throws Exception {
return new SecretKeySpec(Arrays.copyOf(MessageDigest.getInstance("SHA-256").digest(password.getBytes(StandardCharsets.UTF_8)),
16), "AES");
}
public String encrypt(String text, String password) throws Exception {
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key(password));
return Base64.getEncoder().encodeToString(c.doFinal(text.getBytes(StandardCharsets.UTF_8)));
}
public String decrypt(String value, String password) throws Exception {
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, key(password));
return new String(c.doFinal(Base64.getDecoder().decode(value)), StandardCharsets.UTF_8);
}
}
projects/32-crypto/modern/src/main/java/at/aydin/lab/crypto/modern/AesGcmService.java
package at.aydin.lab.crypto.modern;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
// Design Pattern: Security Gateway
// Zweck: Sichere kryptografische Parameter werden zentral erzwungen.
public final class AesGcmService {
private final SecureRandom random = new SecureRandom();
private SecretKey key(char[] password, byte[] salt) throws Exception {
var f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
return new SecretKeySpec(f.generateSecret(new PBEKeySpec(password, salt, 120_000, 256)).getEncoded(), "AES");
}
public EncryptedPayload encrypt(String text, char[] password) throws Exception {
byte[] salt = new byte[16], iv = new byte[12];
random.nextBytes(salt);
random.nextBytes(iv);
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
c.init(Cipher.ENCRYPT_MODE, key(password, salt), new GCMParameterSpec(128, iv));
return new EncryptedPayload(salt, iv, c.doFinal(text.getBytes(StandardCharsets.UTF_8)));
}
public String decrypt(EncryptedPayload p, char[] password) throws Exception {
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
c.init(Cipher.DECRYPT_MODE, key(password, p.salt()), new GCMParameterSpec(128, p.iv()));
return new String(c.doFinal(p.cipherText()), StandardCharsets.UTF_8);
}
}
projects/32-crypto/modern/src/main/java/at/aydin/lab/crypto/modern/EncryptedPayload.java
package at.aydin.lab.crypto.modern;
// Design Pattern: Value Object
// Zweck: Ciphertext, Salt und IV bleiben als untrennbare verschlüsselte Nutzlast zusammen.
public record EncryptedPayload(byte[] salt, byte[] iv, byte[] cipherText) {
public EncryptedPayload {
salt = salt.clone();
iv = iv.clone();
cipherText = cipherText.clone();
}
public byte[] salt() {
return salt.clone();
}
public byte[] iv() {
return iv.clone();
}
public byte[] cipherText() {
return cipherText.clone();
}
}
| ID | Ebene | Prüfung | erforderlicher Nachweis |
|---|---|---|---|
| 32-CRYPTO-A01 | Integration/Contract | Manipulierter Ciphertext wird sicher abgewiesen. | Automatisierter Test und CI-Protokoll |
| 32-CRYPTO-A02 | Integration/Contract | Gleicher Klartext erzeugt unterschiedliche Payloads. | Automatisierter Test und CI-Protokoll |
| 32-CRYPTO-A03 | Integration/Contract | Legacy-Daten können kontrolliert gelesen/migriert werden. | Automatisierter Test und CI-Protokoll |
| 32-CRYPTO-A04 | Integration/Contract | Keine ECB-Neuschreibungen. | Automatisierter Test und CI-Protokoll |
| 32-CRYPTO-A05 | Integration/Contract | Key-Rotation und Formatversion sind vorgesehen. | Automatisierter Test und CI-Protokoll |
| 32-CRYPTO-T01 | Unit | Fachlogik ohne Container oder externen Dienst testen. | Unit-Test |
| 32-CRYPTO-T02 | Regression | Legacy- und Modern-Ergebnis für denselben Golden-Master-Vektor vergleichen. | Vergleichsreport |
| 32-CRYPTO-T03 | Negative | Fehlerhafte, leere und grenzwertige Eingaben prüfen. | Negativtest |
| 32-CRYPTO-T04 | Operations | Start, Health, Shutdown und Konfigurationsfehler prüfen. | Deployment-/Startprotokoll |
| 32-CRYPTO-T05 | Security | Manipulation, falsche Schlüssel/Tags und Rückwärtslesbarkeit prüfen. | Security-Test |
| 32-CRYPTO-F01 | Fokus | tamper, wrong key, nonce uniqueness and empty payload tests | Modulspezifischer Testreport |
| Risiko | Auswirkung | Gegenmaßnahme | Gate |
|---|---|---|---|
| confidentiality/integrity failure and nonce misuse | NIEDRIG | tamper, wrong key, nonce uniqueness and empty payload tests | vor Cutover |
Keine zusätzlichen Ressourcen.
Write-new darf nicht auf unsichere ECB-Schreibweise zurückfallen; nur ein zeitlich begrenzter Legacy-Decryptor bleibt für Bestandsdaten.