AES/ECB ohne Authentifizierung
ECB verschlüsselt gleiche Klartextblöcke identisch und erkennt Manipulation nicht.
Vollständiger Legacy-Modern-Vergleich aller Java-Klassen, Tests, Maven-POMs und relevanten Ressourcen dieses Moduls. Jede Datei ist genau einmal einer fachlich passenden Vergleichsgruppe zugeordnet.
ECB verschlüsselt gleiche Klartextblöcke identisch und erkennt Manipulation nicht.
GCM liefert Vertraulichkeit und Integrität; ein zufälliger Nonce wird mit dem Ciphertext gespeichert.
Die Ähnlichkeit ist eine technische Orientierung auf normalisiertem Quelltext. Sie ersetzt keine fachliche Bewertung.
| Vergleichsgruppe | Legacy-Dateien | Modern-Dateien | Legacy-Zeilen | Modern-Zeilen | Ähnlichkeit |
|---|---|---|---|---|---|
| Build-Konfiguration | 1 | 1 | 34 | 34 | 100% |
| Verschlüsselungsservice, Payload und Test | 2 | 3 | 41 | 69 | 41% |
Das Pair-POM bindet die Legacy- und Modern-Submodule zusammen und gehört deshalb ebenfalls zur vollständigen Codeabdeckung.
Crypto-/Testkonfiguration wird verglichen.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| pom.xml | pom.xml | Direktvergleich Semantische Ähnlichkeit: 100% |
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.aydin.academy</groupId>
<artifactId>32crypto-pair</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>crypto-legacy</artifactId>
<packaging>jar</packaging>
<name>Crypto Legacy</name>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.aydin.academy</groupId>
<artifactId>32crypto-pair</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>crypto-modern</artifactId>
<packaging>jar</packaging>
<name>Crypto Modern</name>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>ECB ohne Authentisierung wird GCM mit IV und authentisiertem Payload gegenübergestellt.
| Legacy-Dateien | Modern-Dateien | Einordnung |
|---|---|---|
| LegacyAesEcb.java LegacyAesEcbTest.java | AesGcmService.java EncryptedPayload.java AesGcmServiceTest.java | Direktvergleich Semantische Ähnlichkeit: 41% |
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);
}
}package at.aydin.lab.crypto.legacy;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class LegacyAesEcbTest {
@Test
void isDeterministicAntiPattern() throws Exception {
var c = new LegacyAesEcb();
assertEquals(c.encrypt("text", "pw"), c.encrypt("text", "pw"));
assertEquals("text", c.decrypt(c.encrypt("text", "pw"), "pw"));
}
}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);
}
}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();
}
}package at.aydin.lab.crypto.modern;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AesGcmServiceTest {
@Test
void encryptsRandomizedAndAuthenticated() throws Exception {
var s = new AesGcmService();
var a = s.encrypt("text", "pw".toCharArray());
var b = s.encrypt("text", "pw".toCharArray());
assertFalse(java.util.Arrays.equals(a.cipherText(), b.cipherText()));
assertEquals("text", s.decrypt(a, "pw".toCharArray()));
}
}