Refactor and expand core functionalities with new modules

Added robust utility modules: Tone generation, image scaling, and sound tone mapping. Developed an encryption domain with new abstractions. Updated and annotated the SQL query class for clarity and functionality. Removed unused `@Config` annotation.
This commit is contained in:
Konrad Neitzel
2025-04-02 22:09:02 +02:00
parent 8694899e57
commit 77ea70f4e6
21 changed files with 2754 additions and 904 deletions
@@ -0,0 +1,41 @@
package de.neitzel.encryption;
import com.idealista.fpe.config.Alphabet;
public abstract class BaseAlphabet implements Alphabet {
/**
* Replaces illegal characters of a string with a given replacement character
* @param text Text to check.
* @param replacement Replacement character.
* @return String in which all characters was replaced.
*/
public String replaceIllegalCharacters(String text, char replacement) {
// Validate
if (!isValidCharacter(replacement)) throw new IllegalArgumentException("replacement");
StringBuilder result = new StringBuilder();
for (char ch: text.toCharArray()) {
if (isValidCharacter(ch)){
result.append(ch);
} else {
result.append(replacement);
}
}
return result.toString();
}
/**
* Checks if a given Character is part of the alphabet.
* @param character Character to check.
* @return true if character is valid, else false.
*/
public boolean isValidCharacter(char character) {
// Compare with all characters
for (char ch : availableCharacters()) {
if (ch == character) return true;
}
// Character not found.
return false;
}
}
@@ -0,0 +1,140 @@
package de.neitzel.encryption;
import com.idealista.fpe.FormatPreservingEncryption;
import com.idealista.fpe.builder.FormatPreservingEncryptionBuilder;
import com.idealista.fpe.config.Domain;
import com.idealista.fpe.config.LengthRange;
import javax.crypto.KeyGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
/**
* Helper class to deal with FF1Encryption using com.idealista:format-preserving-encryption:1.0.0.
*/
public class FF1Encryption {
/**
* Key to use for all encryption / unencryption
*/
private byte[] key;
/**
* Should to small strings be ignored?
*
* If this is set to true, small strings (less than 2 characters) will not be encrypted!
*/
private boolean ignoreToShortStrings;
/**
* tweak to use for encryption
*/
private byte[] tweak;
/**
* Domain used for encryption
*/
private Domain domain;
/**
* Format preserving encryption to use.
*/
private FormatPreservingEncryption encryption;
/**
* Minimum length of a string.
*/
private int minLength;
/**
* Creates a new instance of FF1Encryption
* @param key AES key to use.
* @param tweak tweak to use for encryption / decryption
* @param ignoreToShortStrings Ignore strings that are to short.
*/
public FF1Encryption(byte[] key, byte[] tweak, boolean ignoreToShortStrings) {
this(key, tweak, ignoreToShortStrings, new MainDomain(), 2, 1024);
}
/**
* Creates a new instance of FF1Encryption
* @param key AES key to use.
* @param tweak tweak to use for encryption / decryption
* @param ignoreToShortStrings Ignore strings that are to short.
* @param domain Domain to use for encryption
* @param minLength Minimum length of string.
* @param maxLength Maximum length of string.
*/
public FF1Encryption(byte[] key, byte[] tweak, boolean ignoreToShortStrings, Domain domain, int minLength, int maxLength) {
this.key = key;
this.tweak = tweak;
this.ignoreToShortStrings = ignoreToShortStrings;
this.domain = domain;
this.minLength = minLength;
encryption = FormatPreservingEncryptionBuilder
.ff1Implementation().withDomain(domain)
.withDefaultPseudoRandomFunction(key)
.withLengthRange(new LengthRange(minLength, maxLength))
.build();
}
/**
* Encrypts a given text.
* @param plainText Unencrypted text.
* @return Encrypted text.
*/
public String encrypt(String plainText) {
// Handle null
if (plainText == null) return null;
// Handle short strings
if (plainText.length() < minLength && ignoreToShortStrings) return plainText;
// Return encrypted text.
return encryption.encrypt(plainText, tweak);
}
/**
* Decrypt a given text.
* @param cipherText Encrypted text.
* @return Decrypted text.
*/
public String decrypt(String cipherText) {
// Handle null
if (cipherText == null) return null;
// Handle short strings
if (cipherText.length() < minLength && ignoreToShortStrings) return cipherText;
// Return decrypted text.
return encryption.decrypt(cipherText, tweak);
}
/**
* Creates a new AES key woth the given length.
* @param length Length of the key in bits. Must be 128, 192 or 256 bits
* @return Byte array of the new key.
*/
public static byte[] createNewKey(int length) {
try {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(length); // for example
return keyGen.generateKey().getEncoded();
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
}
/**
* Creates a new tweak of the given length.
* @param length Number of bytes the new teeak should have.
* @return byte array with the new tweak.
*/
public static byte[] createNewTweak(int length) {
Random random = new Random();
byte[] key = new byte[length];
random.nextBytes(key);
return key;
}
}
@@ -0,0 +1,48 @@
package de.neitzel.encryption;
/**
* Main characters of the Alphabet.
*/
public class MainAlphabet extends BaseAlphabet {
/**
* All characters we want to use.
*/
private static final char[] ALL_CHARS = new char[] {
// lowercase characters
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
// uppercase characters
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
// numbers
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
// special characters
'-', '_', '?', ' ', '#', '+', '/', '*', '!', '\"', '§', '$', '%', '&', '(', ')', '=', '@',
'€', ',', ';', '.', ':', '<', '>', '|', '\'', '\\', '{', '}', '[', ']',
// german special characters
'ä', 'Ä', 'ö', 'Ö', 'ü', 'Ü', 'ß'
};
/**
* Gets the available characters.
* @return
*/
@Override
public char[] availableCharacters() {
return ALL_CHARS;
}
/**
* Gets the radix of the alphabet.
* @return
*/
@Override
public Integer radix() {
return ALL_CHARS.length;
}
}
@@ -0,0 +1,31 @@
package de.neitzel.encryption;
import com.idealista.fpe.config.Alphabet;
import com.idealista.fpe.config.Domain;
import com.idealista.fpe.config.GenericTransformations;
public class MainDomain implements Domain {
private Alphabet _alphabet;
private GenericTransformations transformations;
public MainDomain() {
_alphabet = new MainAlphabet();
transformations = new GenericTransformations(_alphabet.availableCharacters());
}
@Override
public Alphabet alphabet() {
return _alphabet;
}
@Override
public int[] transform(String data) {
return transformations.transform(data);
}
@Override
public String transform(int[] data) {
return transformations.transform(data);
}
}