package warden;
import java.io.*;
import util.ByteFromIntArray;
public class WardenSHA1
{
private int[] bitlen = new int[2];
private int[] state = new int[0x15];
public static int[] hash(byte []data)
{
return WardenSHA1.hash(byteArrayToCharArray(data));
}
public static int[] hash(char []data)
{
WardenSHA1 ctx = new WardenSHA1();
ctx.update(data);
return ctx.digest();
}
public static int[] hash(String data)
{
return WardenSHA1.hash(data.toCharArray());
}
public WardenSHA1()
{
bitlen[0] = 0;
bitlen[1] = 0;
state[0] = 0x67452301;
state[1] = 0xEFCDAB89;
state[2] = 0x98BADCFE;
state[3] = 0x10325476;
state[4] = 0xC3D2E1F0;
}
private static int reverseEndian(int i)
{
i = (( i << 24) & 0xFF000000) |
((i << 8) & 0x00FF0000) |
((i >> 8) & 0x0000FF00) |
((i >> 24) & 0x000000FF);
return i;
}
public int[] digest()
{
byte[] vars;
int len;
char[] MysteryBuffer;
int[] temp_vars = new int[2];
temp_vars[0] = WardenSHA1.reverseEndian(bitlen[1]);
temp_vars[1] = WardenSHA1.reverseEndian(bitlen[0]);
len = ((-9 - (bitlen[0] >>> 3)) & 0x3F) + 1;
vars = (new ByteFromIntArray(true)).getByteArray(temp_vars);
MysteryBuffer = new char[len];
MysteryBuffer[0] = (char) 0x80;
for (int x = 1; x < len; x++)
MysteryBuffer[x] = (char) 0;
update(MysteryBuffer);
update(byteArrayToCharArray(vars));
int[] hash = new int[5];
for (int x = 0; x < 5; x++)
hash[x] = WardenSHA1.reverseEndian(state[x]);
return hash;
}
public void update(byte[] data)
{
this.update(WardenSHA1.byteArrayToCharArray(data));
}
public void update(char[] data)
{
int a = 0, b = 0, c = 0, x = 0, len = data.length;
c = len >> 29;
b = len << 3;
a = (bitlen[0] / 8) & 0x3F;
if (bitlen[0] + b < bitlen[0] || bitlen[0] + b < b)
bitlen[1]++;
bitlen[0] += b;
bitlen[1] += c;
len += a;
x = -a;
ByteFromIntArray bfia = new ByteFromIntArray(true);
if (len >= 0x40)
{
if (a > 0)
{
while (a < 0x40)
{
bfia.insertByte(state, a + 0x14, (byte) data[a + x]);
a++;
}
transform(state);
len -= 0x40;
x += 0x40;
a = 0;
}
if (len >= 0x40)
{
b = len;
for (int i = 0; i < b / 0x40; i++)
{
for (int y = 0; y < 0x40; y++)
bfia.insertByte(state, y + 0x14, (byte) data[x + y]);
transform(state);
len -= 0x40;
x += 0x40;
}
}
}
while (a < len)
{
bfia.insertByte(state, 20 + a, (byte) data[a + x]);
a++;
}
return;
}
private static void transform(int[] hashBuffer)
{
int buf[] = new int[0x50];
int dw, a, b, c, d, e, p, i;
for(i = 5; i < hashBuffer.length; i++)
hashBuffer[i] = WardenSHA1.reverseEndian(hashBuffer[i]);
for (i = 0; i < 0x10; i++)
buf[i] = hashBuffer[i + 5];
for (i = 0; i < 0x40; i++)
{
dw = buf[i + 13] ^ buf[i + 8] ^ buf[i + 0] ^ buf[i + 2];
buf[i + 16] = (dw >>> 0x1f) | (dw << 1);
}
a = hashBuffer[0];
b = hashBuffer[1];
c = hashBuffer[2];
d = hashBuffer[3];
e = hashBuffer[4];
p = 0;
i = 0x14;
do
{
dw = ((a << 5) | (a >>> 0x1b)) + ((~b & d) | (c & b)) + e + buf[p++] + 0x5a827999;
e = d;
d = c;
c = (b >>> 2) | (b << 0x1e);
b = a;
a = dw;
}
while (--i > 0);
i = 0x14;
do
{
dw = (d ^ c ^ b) + e + ((a << 5) | (a >>> 0x1b)) + buf[p++] + 0x6ED9EBA1;
e = d;
d = c;
c = (b >>> 2) | (b << 0x1e);
b = a;
a = dw;
}
while (--i > 0);
i = 0x14;
do
{
dw = ((c & b) | (d & c) | (d & b)) + e + ((a << 5) | (a >>> 0x1b)) + buf[p++] - 0x70E44324;
e = d;
d = c;
c = (b >>> 2) | (b << 0x1e);
b = a;
a = dw;
}
while (--i > 0);
i = 0x14;
do
{
dw = ((a << 5) | (a >>> 0x1b)) + e + (d ^ c ^ b) + buf[p++] - 0x359D3E2A;
e = d;
d = c;
c = (b >>> 2) | (b << 0x1e);
b = a;
a = dw;
}
while (--i > 0);
hashBuffer[0] += a;
hashBuffer[1] += b;
hashBuffer[2] += c;
hashBuffer[3] += d;
hashBuffer[4] += e;
}
public void pad(int amount)
{
char[] emptybuffer = new char[0x1000];
for (int x = 0; x < 0x1000; x++)
emptybuffer[x] = (byte) 0;
while (amount > 0x1000)
{
update(emptybuffer);
amount -= 0x1000;
}
emptybuffer = new char[amount];
for (int x = 0; x < amount; x++)
emptybuffer[x] = (byte) 0;
update(emptybuffer);
}
public boolean hash_file(String filename)
{
try
{
byte[] data = new byte[(int) (new File(filename)).length()];
InputStream in = new FileInputStream(filename);
in.read(data);
in.close();
update(byteArrayToCharArray(data));
}
catch (Exception e)
{
System.out.println("lockdown_SHA1.hash_file(" + filename + ") Failed: " + e.toString());
return false;
}
return true;
}
private static char[] byteArrayToCharArray(byte[] a)
{
char[] buff = new char[a.length];
for (int x = 0; x < a.length; x++)
buff[x] = (char) (a[x] & 0x000000FF);
return buff;
}
public static void main(String[] args)
{
String test1 = "";
String test2 = "The quick brown fox jumps over the lazy dog";
String test3 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
String test4 = "~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./";
String test5 = "";
int i;
int[] result;
for(i = 0; i < 0x100; i++)
test5 = test5 + (char) i;
result = WardenSHA1.hash(test1);
System.out.format("%08x %08x %08x %08x %08x\n", result[0], result[1], result[2], result[3], result[4]);
System.out.println("eea339da 0d4b6b5e efbf5532 90186095 0907d8af");
System.out.println();
result = WardenSHA1.hash(test2);
System.out.format("%08x %08x %08x %08x %08x\n", result[0], result[1], result[2], result[3], result[4]);
System.out.println("c6e1d42f fc282d7a e19e84ed 39e776bb 12eb931b");
System.out.println();
result = WardenSHA1.hash(test3);
System.out.format("%08x %08x %08x %08x %08x\n", result[0], result[1], result[2], result[3], result[4]);
System.out.println("4d64e33a f5a17767 eaef1d6a 9caf74bc 493e314b");
System.out.println();
result = WardenSHA1.hash(test4);
System.out.format("%08x %08x %08x %08x %08x\n", result[0], result[1], result[2], result[3], result[4]);
System.out.println("df847112 54412b8d 7cf95a20 c8e1622c 598e0878");
System.out.println();
result = WardenSHA1.hash(test5);
System.out.format("%08x %08x %08x %08x %08x\n", result[0], result[1], result[2], result[3], result[4]);
System.out.println("bdd61649 688ef7b7 ab8c6903 6e58d132 c8df57a4");
System.out.println();
}
}
/*
* ByteFromIntArray.java
*
* Created on May 21, 2004, 11:39 AM
*/
package util;
/** This is a class to take care of treating an array of ints like a an array of bytes.
* Note that this always works in Little Endian
*/
public class ByteFromIntArray
{
private boolean littleEndian;
public static final ByteFromIntArray LITTLEENDIAN = new ByteFromIntArray(true);
public static final ByteFromIntArray BIGENDIAN = new ByteFromIntArray(false);
/**
* @param args the command line arguments
*/
/*public static void main(String[] args)
{
int []test = { 0x01234567, 0x89abcdef };
ByteFromIntArray bfia = new ByteFromIntArray(false);
byte []newArray = bfia.getByteArray(test);
for(int i = 0; i < newArray.length; i++)
System.out.print(" " + PadString.padHex(newArray[i], 2));
}*/
public ByteFromIntArray(boolean littleEndian)
{
this.littleEndian = littleEndian;
}
public byte getByte(int[] array, int location)
{
if((location / 4) >= array.length)
throw new ArrayIndexOutOfBoundsException("location = " + location + ", number of bytes = " + (array.length * 4));
int theInt = location / 4; // rounded
int theByte = location % 4; // remainder
// reverse the byte to simulate little endian
if(littleEndian)
theByte = 3 - theByte;
// I was worried about sign-extension here, but then I realized that they are being
// put into a byte anyway so it wouldn't matter.
if(theByte == 0)
return (byte)((array[theInt] & 0x000000FF) >> 0);
else if(theByte == 1)
return (byte)((array[theInt] & 0x0000FF00) >> 8);
else if(theByte == 2)
return (byte)((array[theInt] & 0x00FF0000) >> 16);
else if(theByte == 3)
return (byte)((array[theInt] & 0xFF000000) >> 24);
return 0;
}
/** This function is used to insert the byte into a specified spot in
* an int array. This is used to simulate pointers used in C++.
* Note that this works in little endian only.
* @param intBuffer The buffer to insert the int into.
* @param b The byte we're inserting.
* @param location The location (which byte) we're inserting it into.
* @return The new array - this is returned for convenience only.
*/
public int[] insertByte(int[] intBuffer, int location, byte b)
{
// Get the location in the array and in the int
int theInt = location / 4;
int theByte = location % 4;
// If we're using little endian reverse the hex position
if(littleEndian == false)
theByte = 3 - theByte;
int replaceInt = intBuffer[theInt];
// Creating a new variable here because b is a byte and I need an int
int newByte = b << (8 * theByte);
if(theByte == 0)
replaceInt &= 0xFFFFFF00;
else if(theByte == 1)
replaceInt &= 0xFFFF00FF;
else if(theByte == 2)
replaceInt &= 0xFF00FFFF;
else if(theByte == 3)
replaceInt &= 0x00FFFFFF;
replaceInt = replaceInt | newByte;
intBuffer[theInt] = replaceInt;
return intBuffer;
}
public byte[] getByteArray(int[] array)
{
byte[] newArray = new byte[array.length * 4];
int pos = 0;
for(int i = 0; i < array.length; i++)
{
if(littleEndian)
{
newArray[pos++] = (byte)((array[i] >> 0) & 0xFF);
newArray[pos++] = (byte)((array[i] >> 8) & 0xFF);
newArray[pos++] = (byte)((array[i] >> 16) & 0xFF);
newArray[pos++] = (byte)((array[i] >> 24) & 0xFF);
}
else
{
newArray[pos++] = (byte)((array[i] >> 24) & 0xFF);
newArray[pos++] = (byte)((array[i] >> 16) & 0xFF);
newArray[pos++] = (byte)((array[i] >> 8) & 0xFF);
newArray[pos++] = (byte)((array[i] >> 0) & 0xFF);
}
}
return newArray;
}
public byte[] getByteArray(int integer)
{
int[] temp = new int[1];
temp[0] = integer;
return getByteArray(temp);
}
}