package au.net.causal.projo.prefs.security;
import org.jasypt.encryption.ByteEncryptor;
import org.jasypt.encryption.pbe.PBEByteEncryptor;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import au.net.causal.projo.prefs.PreferencesException;
/**
* A byte encrypter that wraps an underlying byte encrypter that uses a {@link PasswordSource} to configure a password on it the first time it is used.
*
* @author prunge
*/
public class SourcedByteEncrypter implements ByteEncryptor
{
private final PBEByteEncryptor encrypter;
private final PasswordSource passwordSource;
private boolean passwordSet;
/**
* Creates a <code>SourcedByteEncrypter</code>.
*
* @param encrypter the underlying encrypter to use.
* @param passwordSource the source to read the encryption password from.
*/
public SourcedByteEncrypter(PBEByteEncryptor encrypter, PasswordSource passwordSource)
{
if (encrypter == null)
throw new NullPointerException("encrypter == null");
if (passwordSource == null)
throw new NullPointerException("passwordSource == null");
this.encrypter = encrypter;
this.passwordSource = passwordSource;
}
@Override
public byte[] encrypt(byte[] message)
{
configurePasswordIfNeeded(PasswordSource.Mode.ENCRYPTION);
return(encrypter.encrypt(message));
}
@Override
public byte[] decrypt(byte[] encryptedMessage)
{
configurePasswordIfNeeded(PasswordSource.Mode.DECRYPTION);
return(encrypter.decrypt(encryptedMessage));
}
private synchronized void configurePasswordIfNeeded(PasswordSource.Mode mode)
{
if (passwordSet)
return;
try
{
char[] password = passwordSource.readPassword(mode);
if (password == null)
throw new UserAbortedEnteringPasswordException();
encrypter.setPassword(String.valueOf(password));
passwordSet = true;
}
catch (PreferencesException e)
{
throw new EncryptionOperationNotPossibleException(e);
}
}
}