package org.jboss.crypto.digest;
import java.io.ByteArrayOutputStream;
import java.security.MessageDigest;
import java.security.MessageDigestSpi;
import java.security.NoSuchAlgorithmException;
import java.security.ProviderException;
public class SHAInterleave extends MessageDigestSpi
{
private static final int SHA_HASH_LEN = 20;
private ByteArrayOutputStream evenBytes;
private ByteArrayOutputStream oddBytes;
private int count;
private boolean skipLeadingZeros;
private MessageDigest sha;
public SHAInterleave()
{
try
{
sha = MessageDigest.getInstance("SHA");
}
catch(NoSuchAlgorithmException e)
{
throw new ProviderException("Failed to obtain SHA MessageDigest");
}
evenBytes = new ByteArrayOutputStream();
oddBytes = new ByteArrayOutputStream();
engineReset();
}
protected int engineGetDigestLength()
{
return 2 * SHA_HASH_LEN;
}
protected byte[] engineDigest()
{
byte[] E = evenBytes.toByteArray();
byte[] G = sha.digest(E);
byte[] F = oddBytes.toByteArray();
int offset = 0;
if( count % 2 == 1 )
offset = 1;
sha.reset();
sha.update(F, offset, F.length-offset);
byte[] H = sha.digest();
int length = G.length + H.length;
byte[] digest = new byte[length];
for(int i = 0; i < G.length; ++i)
digest[2 * i] = G[i];
for(int i = 0; i < H.length; ++i)
digest[2 * i + 1] = H[i];
engineReset();
return digest;
}
protected void engineReset()
{
skipLeadingZeros = true;
count = 0;
evenBytes.reset();
oddBytes.reset();
sha.reset();
}
protected void engineUpdate(byte input)
{
if( skipLeadingZeros == true && input == 0 )
return;
skipLeadingZeros = false;
if( count % 2 == 0 )
evenBytes.write(input);
else
oddBytes.write(input);
count ++;
}
protected void engineUpdate(byte[] input, int offset, int len)
{
for(int i = offset; i < offset+len; i ++)
engineUpdate(input[i]);
}
}