/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.bean;
import org.bouncycastle.crypto.Digest;
import org.cryptacular.spec.Spec;
import org.cryptacular.util.HashUtil;
/**
* Abstract base class for all hash beans.
*
* @author Middleware Services
*/
public abstract class AbstractHashBean
{
/** Digest specification. */
private Spec<Digest> digestSpec;
/** Number of hash rounds. */
private int iterations = 1;
/** Creates a new instance. */
public AbstractHashBean() {}
/**
* Creates a new instance by specifying all properties.
*
* @param digestSpec Digest specification.
* @param iterations Number of hash rounds.
*/
public AbstractHashBean(final Spec<Digest> digestSpec, final int iterations)
{
setDigestSpec(digestSpec);
setIterations(iterations);
}
/** @return Digest specification that determines the instance of {@link Digest} used to compute the hash. */
public Spec<Digest> getDigestSpec()
{
return digestSpec;
}
/**
* Sets the digest specification that determines the instance of {@link Digest} used to compute the hash.
*
* @param digestSpec Digest algorithm specification.
*/
public void setDigestSpec(final Spec<Digest> digestSpec)
{
this.digestSpec = digestSpec;
}
/** @return Number of iterations the digest function is applied to the input data. */
public int getIterations()
{
return iterations;
}
/**
* Sets the number of iterations the digest function is applied to the input data.
*
* @param iterations Number of hash rounds. Default value is 1.
*/
public void setIterations(final int iterations)
{
if (iterations < 1) {
throw new IllegalArgumentException("Iterations must be positive");
}
this.iterations = iterations;
}
/**
* Hashes the given data.
*
* @param data Data to hash.
*
* @return Digest output.
*/
protected byte[] hashInternal(final Object... data)
{
return HashUtil.hash(digestSpec.newInstance(), iterations, data);
}
/**
* Compares the hash of the given data against a known hash output.
*
* @param hash Known hash value. If the length of the array is greater than the length of the digest output,
* anything beyond the digest length is considered salt data that is hashed <strong>after</strong> the
* input data.
* @param data Data to hash.
*
* @return True if hashed data equals known hash output, false otherwise.
*/
protected boolean compareInternal(final byte[] hash, final Object... data)
{
return HashUtil.compareHash(digestSpec.newInstance(), hash, iterations, data);
}
}