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;
import java.util.Arrays;
public class SHAReverseInterleave 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 SHAReverseInterleave()
{
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();
int length = E.length;
if( count % 2 == 1 )
length --;
byte[] tmp = new byte[length];
for(int i = 0; i < length; i ++)
{
tmp[i] = E[E.length - i - 1];
System.out.println("E["+i+"] = "+tmp[i]);
}
E = tmp;
byte[] G = sha.digest(E);
byte[] F = oddBytes.toByteArray();
tmp = new byte[F.length];
for(int i = 0; i < F.length; i ++)
{
tmp[i] = F[F.length - i - 1];
System.out.println("F["+i+"] = "+tmp[i]);
}
F = tmp;
sha.reset();
byte[] H = sha.digest(F);
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]);
}
}