SHA1 in Java
Jump to navigation
Jump to search
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); } }