Encrypt.java
package org.flasby.settings;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Iterator;
import java.util.Map.Entry;
import org.flasby.crypto.CryptoUtils;
import org.flasby.crypto.CryptoUtils.CipherPair;
/**
* encrypts all key value pairs when adding them as a setting. decrypting will generate a new Cipher
* instance for decryption as every encrypted value will likely have a different IV.
*/
public class Encrypt implements SimpleSettings {
private static final byte[] DEFAULT_SALT = {
(byte) 0xA9,
(byte) 0x9B,
(byte) 0xC8,
(byte) 0x32,
(byte) 0x56,
(byte) 0x35,
(byte) 0xE3,
(byte) 0x03
};
private static final byte[] DEFAULT_IV = {
(byte) 0xA9,
(byte) 0x9B,
(byte) 0xC8,
(byte) 0x32,
(byte) 0x56,
(byte) 0x35,
(byte) 0xE3,
(byte) 0x03,
(byte) 0xA9,
(byte) 0x9B,
(byte) 0xC8,
(byte) 0x32,
(byte) 0x56,
(byte) 0x35,
(byte) 0xE3,
(byte) 0x03,
};
private CipherPair cipherPair;
private final SimpleSettings simpleSettings;
/**
* create a wrapped SimpleSettings which is internally encrypted.
*
* @param settings to be encrypted.
*/
public Encrypt(SimpleSettings settings, char[] passPhrase) throws Exception {
this(settings, passPhrase, DEFAULT_SALT, CryptoUtils.DEFAULT_KEY_ALGORITHM);
}
@SuppressFBWarnings(
value = "EI_EXPOSE_REP2",
justification = "Exposed simpleSettings, not a bug, works as designed")
public Encrypt(
final SimpleSettings settings,
final char[] passPhrase,
final byte[] salt,
final String keyAlgorithm)
throws Exception {
simpleSettings = settings;
// Using the DEFAULT_SALT as it's the correct length - might be a massive error
cipherPair = CryptoUtils.generateCipherPair(passPhrase, DEFAULT_IV);
}
public String encrypt(String toEncrypt) {
byte[] bytes;
try {
bytes = toEncrypt.getBytes(CryptoUtils.ENCODING_CHARSET);
return CryptoUtils.toBase64(encrypt(bytes));
} catch (Exception e) {
throw new RuntimeException("Couldn't encrypt because " + e, e);
}
}
/**
* encrypt the plain byte array and prepend the IV value.
*
* @param toEncrypt
* @return a pair contaiing the IV and the encrypted array of bytes
* @throws Exception
*/
public byte[] encrypt(byte[] toEncrypt) throws Exception {
return cipherPair.enCipher.doFinal(toEncrypt);
}
public String decrypt(String toDecrypt) {
try {
byte[] encrypted = CryptoUtils.fromBase64(toDecrypt);
return new String(decrypt(encrypted), CryptoUtils.ENCODING_CHARSET);
} catch (Exception e) {
throw new RuntimeException("Couldn't decrypt because " + e, e);
}
}
public byte[] decrypt(byte[] encrypt) throws Exception {
return cipherPair.deCipher.doFinal(encrypt);
}
public static void main(String[] args) throws Exception {
String message = "MESSAGEMESSAGEMESSAGEMESSAGEMESSAGEMESSAGE MESSAGE";
String password = "PASSWORD";
Encrypt encrypter = new Encrypt(null, password.toCharArray());
String encrypted = encrypter.encrypt(message);
String decrypted = encrypter.decrypt(encrypted);
System.out.println(
"Encrypt(\"" + message + "\", \"" + password + "\") = \"" + encrypted + "\"");
System.out.println(
"Decrypt(\"" + encrypted + "\", \"" + password + "\") = \"" + decrypted + "\"");
}
// void setPassword( char[] password);
@Override
public Iterator<Entry<String, String>> iterator() {
return simpleSettings.iterator();
}
@Override
public String get(String name) {
String v = getRaw(name);
if (v == null) {
return v;
}
return decrypt(v);
}
@Override
public void add(String name, String value) {
addRaw(name, encrypt(value));
}
@Override
public void remove(String name) {
simpleSettings.remove(name);
}
@Override
public boolean isEmpty() {
return simpleSettings.isEmpty();
}
protected String getRaw(String name) {
return simpleSettings.get(name);
}
protected void addRaw(String name, String value) {
simpleSettings.add(name, value);
}
@Override
public void doIfExists(String name, ApplyWithExistingValue ifExists) {
simpleSettings.doIfExists(name, ifExists);
}
@Override
public void doIfExists(
String key, ApplyWithExistingValue ifExists, ApplyWithMissingKey otherwise) {
if (get(key) != null) {
ifExists.apply(key, get(key));
} else {
otherwise.apply(key);
}
}
}