package gnu.java.security.provider;
import java.security.MessageDigest;
public class SHA extends MessageDigest implements Cloneable
{
public SHA ()
{
super("SHA");
engineReset ();
}
public int engineGetDigestLength()
{
return 20;
}
public void engineUpdate (byte b)
{
int i = ((int)bytecount) & 0x3f; int shift = (3 - i % 4) << 3;
int idx = i / 4;
i = (int)b;
W[idx] = (W[idx] & ~(0xff << shift)) | ((i & 0xff) << shift);
if (((++bytecount) & 0x3f) == 0)
munch ();
}
public void engineUpdate (byte bytes[], int off, int len)
{
if (len < 0)
throw new ArrayIndexOutOfBoundsException ();
int end = off + len;
while (off < end)
engineUpdate (bytes[off++]);
}
public void engineReset ()
{
bytecount = 0;
H0 = 0x67452301;
H1 = 0xefcdab89;
H2 = 0x98badcfe;
H3 = 0x10325476;
H4 = 0xc3d2e1f0;
}
public byte[] engineDigest ()
{
long bitcount = bytecount << 3;
engineUpdate ((byte)0x80);
while ((bytecount & 0x3f) != 56)
engineUpdate ((byte)0);
W[14] = (int)(bitcount >>> 32);
W[15] = (int)bitcount;
bytecount += 8;
munch ();
byte[] result
= new byte[] {(byte)(H0 >>> 24), (byte)(H0 >>> 16),
(byte)(H0 >>> 8), (byte)H0,
(byte)(H1 >>> 24), (byte)(H1 >>> 16),
(byte)(H1 >>> 8), (byte)H1,
(byte)(H2 >>> 24), (byte)(H2 >>> 16),
(byte)(H2 >>> 8), (byte)H2,
(byte)(H3 >>> 24), (byte)(H3 >>> 16),
(byte)(H3 >>> 8), (byte)H3,
(byte)(H4 >>> 24), (byte)(H4 >>> 16),
(byte)(H4 >>> 8), (byte)H4};
engineReset ();
return result;
}
private void munch ()
{
for (int t = 16; t < 80; ++ t)
{
int Wt = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
W[t] = Wt << 1 | Wt >>> 31;
}
int A = H0;
int B = H1;
int C = H2;
int D = H3;
int E = H4;
for (int t = 0; t < 20; ++ t)
{
int TEMP = (A << 5 | A >>> 27) + ((B & C) | (~B & D)) + E + W[t]
+ 0x5a827999;
E = D;
D = C;
C = B << 30 | B >>> 2; B = A;
A = TEMP;
}
for (int t = 20; t < 40; ++ t)
{
int TEMP = (A << 5 | A >>> 27) + (B ^ C ^ D) + E + W[t]
+ 0x6ed9eba1;
E = D;
D = C;
C = B << 30 | B >>> 2; B = A;
A = TEMP;
}
for (int t = 40; t < 60; ++ t)
{
int TEMP = (A << 5 | A >>> 27) + (B & C | B & D | C & D) + E + W[t]
+ 0x8f1bbcdc;
E = D;
D = C;
C = B << 30 | B >>> 2; B = A;
A = TEMP;
}
for (int t = 60; t < 80; ++ t)
{
int TEMP = (A << 5 | A >>> 27) + (B ^ C ^ D) + E + W[t]
+ 0xca62c1d6;
E = D;
D = C;
C = B << 30 | B >>> 2; B = A;
A = TEMP;
}
H0 += A;
H1 += B;
H2 += C;
H3 += D;
H4 += E;
for (int t = 0; t < 80; ++ t)
W[t] = 0;
}
public Object clone ()
{
return new SHA (this);
}
private SHA (SHA copy)
{
this ();
bytecount = copy.bytecount;
H0 = copy.H0;
H1 = copy.H1;
H2 = copy.H2;
H3 = copy.H3;
H4 = copy.H4;
System.arraycopy (copy.W, 0, W, 0, 80);
}
private final int W[] = new int[80];
private long bytecount;
private int H0;
private int H1;
private int H2;
private int H3;
private int H4;
}