/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.bean;
import java.security.KeyStore;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.cryptacular.CiphertextHeader;
import org.cryptacular.adapter.BufferedBlockCipherAdapter;
import org.cryptacular.generator.Nonce;
import org.cryptacular.spec.Spec;
/**
* Cipher bean that performs symmetric encryption/decryption using a standard block cipher in a standard mode (e.g. CBC,
* OFB) with padding to support processing inputs of arbitrary length.
*
* @author Middleware Services
*/
public class BufferedBlockCipherBean extends AbstractBlockCipherBean
{
/** Block cipher specification (algorithm, mode, padding). */
private Spec<BufferedBlockCipher> blockCipherSpec;
/** Creates a new instance. */
public BufferedBlockCipherBean() {}
/**
* Creates a new instance by specifying all properties.
*
* @param blockCipherSpec Block cipher specification.
* @param keyStore Key store containing encryption key.
* @param keyAlias Name of encryption key entry in key store.
* @param keyPassword Password used to decrypt key entry in keystore.
* @param nonce Nonce/IV generator.
*/
public BufferedBlockCipherBean(
final Spec<BufferedBlockCipher> blockCipherSpec,
final KeyStore keyStore,
final String keyAlias,
final String keyPassword,
final Nonce nonce)
{
super(keyStore, keyAlias, keyPassword, nonce);
setBlockCipherSpec(blockCipherSpec);
}
/** @return Block cipher specification. */
public Spec<BufferedBlockCipher> getBlockCipherSpec()
{
return blockCipherSpec;
}
/**
* Sets the block cipher specification.
*
* @param blockCipherSpec Describes a block cipher in terms of algorithm, mode, and padding.
*/
public void setBlockCipherSpec(final Spec<BufferedBlockCipher> blockCipherSpec)
{
this.blockCipherSpec = blockCipherSpec;
}
@Override
protected BufferedBlockCipherAdapter newCipher(final CiphertextHeader header, final boolean mode)
{
final BufferedBlockCipher cipher = blockCipherSpec.newInstance();
CipherParameters params = new KeyParameter(lookupKey(header.getKeyName()).getEncoded());
final String algName = cipher.getUnderlyingCipher().getAlgorithmName();
if (algName.endsWith("CBC") || algName.endsWith("OFB") || algName.endsWith("CFB")) {
params = new ParametersWithIV(params, header.getNonce());
}
cipher.init(mode, params);
return new BufferedBlockCipherAdapter(cipher);
}
}