Stephan Richter
2 months ago
8 changed files with 227 additions and 1 deletions
@ -0,0 +1,22 @@ |
|||||||
|
plugins { |
||||||
|
id 'java' |
||||||
|
} |
||||||
|
|
||||||
|
group = 'de.srsoftware' |
||||||
|
version = '1.0-SNAPSHOT' |
||||||
|
|
||||||
|
repositories { |
||||||
|
mavenCentral() |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
testImplementation platform('org.junit:junit-bom:5.10.0') |
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter' |
||||||
|
implementation project(':de.srsoftware.oidc.api') |
||||||
|
implementation 'com.sun.mail:jakarta.mail:2.0.1' |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
test { |
||||||
|
useJUnitPlatform() |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
/* © SRSoftware 2024 */ |
||||||
|
package de.srsoftware.oidc.datastore.encrypted; |
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8; |
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException; |
||||||
|
import java.security.SecureRandom; |
||||||
|
import java.security.spec.InvalidKeySpecException; |
||||||
|
import java.security.spec.KeySpec; |
||||||
|
import java.util.Base64; |
||||||
|
import javax.crypto.*; |
||||||
|
import javax.crypto.spec.IvParameterSpec; |
||||||
|
import javax.crypto.spec.PBEKeySpec; |
||||||
|
import javax.crypto.spec.SecretKeySpec; |
||||||
|
|
||||||
|
public class EncryptedConfig { |
||||||
|
private final Cipher cipher; |
||||||
|
private static final int KEY_LENGTH = 256; |
||||||
|
private static final int ITERATION_COUNT = 65536; |
||||||
|
private final SecretKeySpec secretKeySpec; |
||||||
|
|
||||||
|
public EncryptedConfig(String key, String salt) { |
||||||
|
try { |
||||||
|
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); |
||||||
|
KeySpec spec = new PBEKeySpec(key.toCharArray(), salt.getBytes(), ITERATION_COUNT, KEY_LENGTH); |
||||||
|
SecretKey tmp = factory.generateSecret(spec); |
||||||
|
secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES"); |
||||||
|
|
||||||
|
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); |
||||||
|
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeySpecException ex) { |
||||||
|
throw new RuntimeException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String encrypt(String plain) { |
||||||
|
SecureRandom secureRandom = new SecureRandom(); |
||||||
|
byte[] iv = new byte[16]; |
||||||
|
secureRandom.nextBytes(iv); |
||||||
|
IvParameterSpec initVector = new IvParameterSpec(iv); |
||||||
|
try { |
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, initVector); |
||||||
|
byte[] cipherText = cipher.doFinal(plain.getBytes(UTF_8)); |
||||||
|
byte[] encryptedData = new byte[iv.length + cipherText.length]; |
||||||
|
System.arraycopy(iv, 0, encryptedData, 0, iv.length); |
||||||
|
System.arraycopy(cipherText, 0, encryptedData, iv.length, cipherText.length); |
||||||
|
|
||||||
|
return Base64.getEncoder().encodeToString(encryptedData); |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String decrypt(String secret) { |
||||||
|
byte[] encryptedData = Base64.getDecoder().decode(secret); |
||||||
|
byte[] iv = new byte[16]; |
||||||
|
System.arraycopy(encryptedData, 0, iv, 0, iv.length); |
||||||
|
IvParameterSpec ivspec = new IvParameterSpec(iv); |
||||||
|
try { |
||||||
|
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec); |
||||||
|
byte[] cipherText = new byte[encryptedData.length - 16]; |
||||||
|
System.arraycopy(encryptedData, 16, cipherText, 0, cipherText.length); |
||||||
|
|
||||||
|
byte[] decryptedText = cipher.doFinal(cipherText); |
||||||
|
return new String(decryptedText, UTF_8); |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,105 @@ |
|||||||
|
/* © SRSoftware 2024 */ |
||||||
|
package de.srsoftware.oidc.datastore.encrypted; |
||||||
|
|
||||||
|
/* © SRSoftware 2024 */ |
||||||
|
|
||||||
|
import static de.srsoftware.oidc.api.Constants.*; |
||||||
|
|
||||||
|
import de.srsoftware.oidc.api.MailConfig; |
||||||
|
import jakarta.mail.Authenticator; |
||||||
|
import jakarta.mail.PasswordAuthentication; |
||||||
|
|
||||||
|
|
||||||
|
public class EncryptedMailConfig extends EncryptedConfig implements MailConfig { |
||||||
|
private final MailConfig storage; |
||||||
|
private Authenticator auth; |
||||||
|
|
||||||
|
public EncryptedMailConfig(MailConfig storage, String encryotionKey, String salt) { |
||||||
|
super(encryotionKey, salt); |
||||||
|
this.storage = storage; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MailConfig save() { |
||||||
|
return storage.save(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String senderAddress() { |
||||||
|
return decrypt(storage.senderAddress()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MailConfig senderAddress(String newValue) { |
||||||
|
storage.senderAddress(encrypt(newValue)); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String senderPassword() { |
||||||
|
return decrypt(storage.senderPassword()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MailConfig senderPassword(String newValue) { |
||||||
|
storage.senderPassword(encrypt(newValue)); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean smtpAuth() { |
||||||
|
return storage.smtpAuth(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MailConfig smtpAuth(boolean newValue) { |
||||||
|
storage.smtpAuth(newValue); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Authenticator authenticator() { |
||||||
|
if (auth == null) { |
||||||
|
auth = new Authenticator() { |
||||||
|
// override the getPasswordAuthentication method
|
||||||
|
protected PasswordAuthentication getPasswordAuthentication() { |
||||||
|
return new PasswordAuthentication(senderAddress(), senderPassword()); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
return auth; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String smtpHost() { |
||||||
|
return decrypt(storage.smtpHost()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MailConfig smtpHost(String newValue) { |
||||||
|
storage.smtpHost(encrypt(newValue)); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int smtpPort() { |
||||||
|
return storage.smtpPort(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MailConfig smtpPort(int newValue) { |
||||||
|
storage.smtpPort(newValue); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean startTls() { |
||||||
|
return storage.startTls(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MailConfig startTls(boolean newValue) { |
||||||
|
storage.startTls(newValue); |
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue