/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular;
import org.cryptacular.codec.Encoder;
import org.cryptacular.util.CodecUtil;
/**
* Container for the output of a salted hash operation that includes both the digest output and salt value.
*
* @author Middleware Services
*/
public class SaltedHash
{
/** Digest output. */
private final byte[] hash;
/** Salt value. */
private final byte[] salt;
/**
* Creates a new instance with digest and salt data.
*
* @param hash Digest output.
* @param salt Salt value used to compute salt.
*/
public SaltedHash(final byte[] hash, final byte[] salt)
{
this.hash = hash;
this.salt = salt;
}
/**
* Creates a new instance from byte input that contains the concatenation of digest output and salt.
*
* @param hashWithSalt Concatenation of hash and salt.
* @param digestLength Number of bytes in digest output.
* @param toEnd True if salt is appended to end of hash, false if salt is prepended to hash.
*/
public SaltedHash(final byte[] hashWithSalt, final int digestLength, final boolean toEnd)
{
this.hash = new byte[digestLength];
this.salt = new byte[hashWithSalt.length - digestLength];
if (toEnd) {
System.arraycopy(hashWithSalt, 0, hash, 0, hash.length);
System.arraycopy(hashWithSalt, hash.length, salt, 0, salt.length);
} else {
System.arraycopy(hashWithSalt, 0, salt, 0, salt.length);
System.arraycopy(hashWithSalt, salt.length, hash, 0, hash.length);
}
}
/** @return Digest output. */
public byte[] getHash()
{
return hash;
}
/** @return Salt value. */
public byte[] getSalt()
{
return salt;
}
/**
* Gets an encoded string of the concatenation of digest output and salt.
*
* @param toEnd True to append salt to end of hash, false to prefix hash with salt.
* @param encoder Encodes concatenated bytes to a string.
*
* @return Salt concatenated to hash encoded as a string.
*/
public String concatenateSalt(final boolean toEnd, final Encoder encoder)
{
return CodecUtil.encode(encoder, concatenateSalt(toEnd));
}
/**
* Gets a byte array containing the concatenation of digest output and salt.
*
* @param toEnd True to append salt to end of hash, false to prefix hash with salt.
*
* @return Salt concatenated to hash.
*/
public byte[] concatenateSalt(final boolean toEnd)
{
final byte[] output = new byte[hash.length + salt.length];
if (toEnd) {
System.arraycopy(hash, 0, output, 0, hash.length);
System.arraycopy(salt, 0, output, hash.length, salt.length);
} else {
System.arraycopy(salt, 0, output, 0, salt.length);
System.arraycopy(hash, 0, output, salt.length, hash.length);
}
return output;
}
}