Difference between revisions of "SHA1 in Java"
Jump to navigation
Jump to search
(New page: == WardenSHA1.java == <pre>package warden; import java.io.*; import util.ByteFromIntArray; public class WardenSHA1 { private int[] bitlen = new int[2]; private int[] state = new int[0...) |
|||
Line 300: | Line 300: | ||
==util.ByteFromIntArray.java== | ==util.ByteFromIntArray.java== | ||
<pre>/* | <pre>/* | ||
* ByteFromIntArray.java | * ByteFromIntArray.java | ||
* | * | ||
* Created on May 21, 2004, 11:39 AM | * Created on May 21, 2004, 11:39 AM | ||
*/ | */ | ||
package util; | package util; | ||
/** This is a class to take care of treating an array of ints like a an array of bytes. | /** 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 | * Note that this always works in Little Endian | ||
*/ | */ | ||
public class ByteFromIntArray | public class ByteFromIntArray | ||
{ | { | ||
private boolean littleEndian; | private boolean littleEndian; | ||
public static final ByteFromIntArray LITTLEENDIAN = new ByteFromIntArray(true); | public static final ByteFromIntArray LITTLEENDIAN = new ByteFromIntArray(true); | ||
public static final ByteFromIntArray BIGENDIAN = new ByteFromIntArray(false); | public static final ByteFromIntArray BIGENDIAN = new ByteFromIntArray(false); | ||
/** | /** | ||
* @param args the command line arguments | * @param args the command line arguments | ||
*/ | */ | ||
/*public static void main(String[] args) | /*public static void main(String[] args) | ||
{ | { | ||
int []test = { 0x01234567, 0x89abcdef }; | int []test = { 0x01234567, 0x89abcdef }; | ||
ByteFromIntArray bfia = new ByteFromIntArray(false); | ByteFromIntArray bfia = new ByteFromIntArray(false); | ||
byte []newArray = bfia.getByteArray(test); | byte []newArray = bfia.getByteArray(test); | ||
for(int i = 0; i < newArray.length; i++) | for(int i = 0; i < newArray.length; i++) | ||
System.out.print(" " + PadString.padHex(newArray[i], 2)); | System.out.print(" " + PadString.padHex(newArray[i], 2)); | ||
}*/ | }*/ | ||
public ByteFromIntArray(boolean littleEndian) | public ByteFromIntArray(boolean littleEndian) | ||
{ | { | ||
this.littleEndian = littleEndian; | this.littleEndian = littleEndian; | ||
} | } | ||
public byte getByte(int[] array, int location) | public byte getByte(int[] array, int location) | ||
{ | { | ||
if((location / 4) >= array.length) | if((location / 4) >= array.length) | ||
throw new ArrayIndexOutOfBoundsException("location = " + location + ", number of bytes = " + (array.length * 4)); | throw new ArrayIndexOutOfBoundsException("location = " + location + ", number of bytes = " + (array.length * 4)); | ||
int theInt = location / 4; // rounded | int theInt = location / 4; // rounded | ||
int theByte = location % 4; // remainder | int theByte = location % 4; // remainder | ||
// reverse the byte to simulate little endian | // reverse the byte to simulate little endian | ||
if(littleEndian) | if(littleEndian) | ||
theByte = 3 - theByte; | theByte = 3 - theByte; | ||
// I was worried about sign-extension here, but then I realized that they are being | // 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. | // put into a byte anyway so it wouldn't matter. | ||
if(theByte == 0) | if(theByte == 0) | ||
return (byte)((array[theInt] & 0x000000FF) >> 0); | return (byte)((array[theInt] & 0x000000FF) >> 0); | ||
else if(theByte == 1) | else if(theByte == 1) | ||
return (byte)((array[theInt] & 0x0000FF00) >> 8); | return (byte)((array[theInt] & 0x0000FF00) >> 8); | ||
else if(theByte == 2) | else if(theByte == 2) | ||
return (byte)((array[theInt] & 0x00FF0000) >> 16); | return (byte)((array[theInt] & 0x00FF0000) >> 16); | ||
else if(theByte == 3) | else if(theByte == 3) | ||
return (byte)((array[theInt] & 0xFF000000) >> 24); | return (byte)((array[theInt] & 0xFF000000) >> 24); | ||
return 0; | return 0; | ||
} | } | ||
/** This function is used to insert the byte into a specified spot in | /** 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++. | * an int array. This is used to simulate pointers used in C++. | ||
* Note that this works in little endian only. | * Note that this works in little endian only. | ||
* @param intBuffer The buffer to insert the int into. | * @param intBuffer The buffer to insert the int into. | ||
* @param b The byte we're inserting. | * @param b The byte we're inserting. | ||
* @param location The location (which byte) we're inserting it into. | * @param location The location (which byte) we're inserting it into. | ||
* @return The new array - this is returned for convenience only. | * @return The new array - this is returned for convenience only. | ||
*/ | */ | ||
public int[] insertByte(int[] intBuffer, int location, byte b) | public int[] insertByte(int[] intBuffer, int location, byte b) | ||
{ | { | ||
// Get the location in the array and in the int | // Get the location in the array and in the int | ||
int theInt = location / 4; | int theInt = location / 4; | ||
int theByte = location % 4; | int theByte = location % 4; | ||
// If we're using little endian reverse the hex position | // If we're using little endian reverse the hex position | ||
if(littleEndian == false) | if(littleEndian == false) | ||
theByte = 3 - theByte; | theByte = 3 - theByte; | ||
int replaceInt = intBuffer[theInt]; | int replaceInt = intBuffer[theInt]; | ||
// Creating a new variable here because b is a byte and I need an int | // Creating a new variable here because b is a byte and I need an int | ||
int newByte = b << (8 * theByte); | int newByte = b << (8 * theByte); | ||
if(theByte == 0) | if(theByte == 0) | ||
replaceInt &= 0xFFFFFF00; | replaceInt &= 0xFFFFFF00; | ||
else if(theByte == 1) | else if(theByte == 1) | ||
replaceInt &= 0xFFFF00FF; | replaceInt &= 0xFFFF00FF; | ||
else if(theByte == 2) | else if(theByte == 2) | ||
replaceInt &= 0xFF00FFFF; | replaceInt &= 0xFF00FFFF; | ||
else if(theByte == 3) | else if(theByte == 3) | ||
replaceInt &= 0x00FFFFFF; | replaceInt &= 0x00FFFFFF; | ||
replaceInt = replaceInt | newByte; | replaceInt = replaceInt | newByte; | ||
intBuffer[theInt] = replaceInt; | intBuffer[theInt] = replaceInt; | ||
return intBuffer; | return intBuffer; | ||
} | } | ||
public byte[] getByteArray(int[] array) | public byte[] getByteArray(int[] array) | ||
{ | { | ||
byte[] newArray = new byte[array.length * 4]; | byte[] newArray = new byte[array.length * 4]; | ||
int pos = 0; | int pos = 0; | ||
for(int i = 0; i < array.length; i++) | for(int i = 0; i < array.length; i++) | ||
{ | { | ||
if(littleEndian) | if(littleEndian) | ||
{ | { | ||
newArray[pos++] = (byte)((array[i] >> 0) & 0xFF); | newArray[pos++] = (byte)((array[i] >> 0) & 0xFF); | ||
newArray[pos++] = (byte)((array[i] >> 8) & 0xFF); | newArray[pos++] = (byte)((array[i] >> 8) & 0xFF); | ||
newArray[pos++] = (byte)((array[i] >> 16) & 0xFF); | newArray[pos++] = (byte)((array[i] >> 16) & 0xFF); | ||
newArray[pos++] = (byte)((array[i] >> 24) & 0xFF); | newArray[pos++] = (byte)((array[i] >> 24) & 0xFF); | ||
} | } | ||
else | else | ||
{ | { | ||
newArray[pos++] = (byte)((array[i] >> 24) & 0xFF); | newArray[pos++] = (byte)((array[i] >> 24) & 0xFF); | ||
newArray[pos++] = (byte)((array[i] >> 16) & 0xFF); | newArray[pos++] = (byte)((array[i] >> 16) & 0xFF); | ||
newArray[pos++] = (byte)((array[i] >> 8) & 0xFF); | newArray[pos++] = (byte)((array[i] >> 8) & 0xFF); | ||
newArray[pos++] = (byte)((array[i] >> 0) & 0xFF); | newArray[pos++] = (byte)((array[i] >> 0) & 0xFF); | ||
} | } | ||
} | } | ||
return newArray; | return newArray; | ||
} | } | ||
public byte[] getByteArray(int integer) | public byte[] getByteArray(int integer) | ||
{ | { | ||
int[] temp = new int[1]; | int[] temp = new int[1]; | ||
temp[0] = integer; | temp[0] = integer; | ||
return getByteArray(temp); | return getByteArray(temp); | ||
} | } | ||
} | } | ||
</pre> | </pre> |
Latest revision as of 03:40, 27 February 2008
WardenSHA1.java
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(); } }
util.ByteFromIntArray.java
/* * 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); } }