/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.spec;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.GOST3411Digest;
import org.bouncycastle.crypto.digests.MD2Digest;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.RIPEMD128Digest;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import org.bouncycastle.crypto.digests.RIPEMD256Digest;
import org.bouncycastle.crypto.digests.RIPEMD320Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.digests.TigerDigest;
import org.bouncycastle.crypto.digests.WhirlpoolDigest;
/**
* Describes a message digest function by name and provides a means to create a new instance of the digest via the
* {@link #newInstance()} method.
*
* @author Middleware Services
*/
public class DigestSpec implements Spec<Digest>
{
/** Digest algorithm name. */
private final String algorithm;
/** Requested size of variable-size hash algorithms, e.g. SHA-3. -1 for hashes with fixed size outputs. */
private final int size;
/**
* Creates a new instance from the given algorithm name.
*
* @param algName Digest algorithm name.
*/
public DigestSpec(final String algName)
{
if (algName == null) {
throw new IllegalArgumentException("Algorithm name is required.");
}
this.algorithm = algName;
this.size = -1;
}
/**
* Constructor for digests that have variable output size, e.g. SHA3.
*
* @param algName Digest algorithm name.
* @param digestSize Size of resultant digest in bits.
*/
public DigestSpec(final String algName, final int digestSize)
{
if (algName == null) {
throw new IllegalArgumentException("Algorithm name is required.");
}
this.algorithm = algName;
if (digestSize < 0) {
throw new IllegalArgumentException("Digest size must be positive.");
}
this.size = digestSize;
}
@Override
public String getAlgorithm()
{
return algorithm;
}
/** @return Size of digest output in bytes, or -1 if the digest does not support variable size output. */
public int getSize()
{
return size;
}
/**
* Creates a new digest instance.
*
* @return Digest instance.
*/
@Override
public Digest newInstance()
{
final Digest digest;
if ("GOST3411".equalsIgnoreCase(algorithm)) {
digest = new GOST3411Digest();
} else if ("MD2".equalsIgnoreCase(algorithm)) {
digest = new MD2Digest();
} else if ("MD4".equalsIgnoreCase(algorithm)) {
digest = new MD4Digest();
} else if ("MD5".equalsIgnoreCase(algorithm)) {
digest = new MD5Digest();
} else if ("RIPEMD128".equalsIgnoreCase(algorithm) || "RIPEMD-128".equalsIgnoreCase(algorithm)) {
digest = new RIPEMD128Digest();
} else if ("RIPEMD160".equalsIgnoreCase(algorithm) || "RIPEMD-160".equalsIgnoreCase(algorithm)) {
digest = new RIPEMD160Digest();
} else if ("RIPEMD256".equalsIgnoreCase(algorithm) || "RIPEMD-256".equalsIgnoreCase(algorithm)) {
digest = new RIPEMD256Digest();
} else if ("RIPEMD320".equalsIgnoreCase(algorithm) || "RIPEMD-320".equalsIgnoreCase(algorithm)) {
digest = new RIPEMD320Digest();
} else if ("SHA1".equalsIgnoreCase(algorithm) || "SHA-1".equalsIgnoreCase(algorithm)) {
digest = new SHA1Digest();
} else if ("SHA224".equalsIgnoreCase(algorithm) || "SHA-224".equalsIgnoreCase(algorithm)) {
digest = new SHA224Digest();
} else if ("SHA256".equalsIgnoreCase(algorithm) || "SHA-256".equalsIgnoreCase(algorithm)) {
digest = new SHA256Digest();
} else if ("SHA384".equalsIgnoreCase(algorithm) || "SHA-384".equalsIgnoreCase(algorithm)) {
digest = new SHA384Digest();
} else if ("SHA512".equalsIgnoreCase(algorithm) || "SHA-512".equalsIgnoreCase(algorithm)) {
digest = new SHA512Digest();
} else if ("SHA3".equalsIgnoreCase(algorithm) || "SHA-3".equalsIgnoreCase(algorithm)) {
digest = new SHA3Digest(size);
} else if ("Tiger".equalsIgnoreCase(algorithm)) {
digest = new TigerDigest();
} else if ("Whirlpool".equalsIgnoreCase(algorithm)) {
digest = new WhirlpoolDigest();
} else {
throw new IllegalStateException("Unsupported digest algorithm " + algorithm);
}
return digest;
}
@Override
public String toString()
{
return algorithm;
}
}