• Welcome to Valhalla Legends Archive.
 

Workaround for int/byte arrays

Started by iago, May 21, 2004, 04:59 PM

Previous topic - Next topic

iago

One annoying part of converting c to Java is when the C programmer uses a byte pointer into an int array or an int pointer into a byte array.  This happens, for instance, in SHA1.  Here is a workaround i wrote for both ways:

/*
* ByteFromIntArray.java
*
* Created on May 21, 2004, 11:39 AM
*/

package bot.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
*
* @author  Ron - Home
*/
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;
   }
}


-- and --

/*
* IntFromByteArray.java
*
* Created on May 21, 2004, 12:35 PM
*/

package bot.util;

/** This is a class to take care of inserting or getting the value of an int in an array of
* bytes.
* @author  Ron - Home
*/
public class IntFromByteArray
{
   private boolean littleEndian;
   
   public static final IntFromByteArray LITTLEENDIAN = new IntFromByteArray(true);
   public static final IntFromByteArray BIGENDIAN = new IntFromByteArray(false);
   
   /**
    * @param args the command line arguments
    */
   
   public static void main(String args[])
   {
       byte[] test = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
       
       IntFromByteArray ifba = new IntFromByteArray(true);
       
       int[] newArray = ifba.getIntArray(test);

       
       for(int i = 0; i < newArray.length; i++)
           System.out.print(PadString.padHex(newArray[i], 8) + " ");
   }

   public IntFromByteArray(boolean littleEndian)
   {
       this.littleEndian = littleEndian;
   }
   public int getInteger(byte[] array, int location)
   {
       if((location + 3) >= array.length)
           throw new ArrayIndexOutOfBoundsException("location = " + location + ", number of bytes = " + array.length + " (note: 4 available bytes are needed)");
       
       int retVal = 0;
       
       // reverse the byte to simulate little endian
       if(littleEndian)
       {
           retVal = retVal | ((array[location++] << 0)  & 0x000000FF);
           retVal = retVal | ((array[location++] << 8)  & 0x0000FF00);
           retVal = retVal | ((array[location++] << 16) & 0x00FF0000);
           retVal = retVal | ((array[location++] << 24) & 0xFF000000);
       }
       else
       {
           retVal = retVal | ((array[location++] << 24) & 0xFF000000);
           retVal = retVal | ((array[location++] << 16) & 0x00FF0000);
           retVal = retVal | ((array[location++] << 8)  & 0x0000FF00);
           retVal = retVal | ((array[location++] << 0)  & 0x000000FF);
       }
       
       return retVal;
   }
   
   
   /** 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 byte[] insertInteger(byte[] array, int location, int b)
   {
       if(location + 3 >= array.length)
           throw new ArrayIndexOutOfBoundsException("location = " + location + ", length = " + array.length + " - note that we need 4 bytes to insert an int");
       
       if(littleEndian)
       {
           array[location++] = (byte)((b & 0x000000FF) >> 0);
           array[location++] = (byte)((b & 0x0000FF00) >> 8);
           array[location++] = (byte)((b & 0x00FF0000) >> 16);
           array[location++] = (byte)((b & 0xFF000000) >> 24);
       }
       else
       {
           array[location++] = (byte)((b & 0xFF000000) >> 24);
           array[location++] = (byte)((b & 0x00FF0000) >> 16);
           array[location++] = (byte)((b & 0x0000FF00) >> 8);
           array[location++] = (byte)((b & 0x000000FF) >> 0);
       }
       
       return array;
   }
   
   /** Note: This will cut off the end bytes to ensure it's a multiple of 4 */
   public int[] getIntArray(byte[] array)
   {
       int[] newArray = new int[array.length / 4];
       
       int pos = 0;
       for(int i = 0; i < newArray.length; i++)
       {
           if(littleEndian)
           {
               newArray[i] |= ((array[pos++] << 0) &  0x000000FF);
               newArray[i] |= ((array[pos++] << 8) &  0x0000FF00);
               newArray[i] |= ((array[pos++] << 16) & 0x00FF0000);
               newArray[i] |= ((array[pos++] << 24) & 0xFF000000);
           }
           else
           {
               newArray[i] |= array[pos++] << 24;
               newArray[i] |= array[pos++] << 16;
               newArray[i] |= array[pos++] << 8;
               newArray[i] |= array[pos++] << 0;
           }
       }
       
       return newArray;
   }
}


If you know of a better way to do this, I would love to hear! :)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


After-Death

I cant read C, how would I find out what the SHA-1 hash does to attempt to write my own in java ?

Tuberload

Quote"Pray not for lighter burdens, but for stronger backs." -- Teddy Roosevelt
"Your forefathers have given you freedom, so good luck, see you around, hope you make it" -- Unknown

iago

If you want real SHA-1, see java.security.MessageDigest.  If you want BrokenSHA1, talk to me privately or even just ask here, I'll post it.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


After-Death

Oh yeah I forget its altered.

Well post it, or if you don't like to post it you have me on AIM: AfterDeaf and PM

Your chat bot that you sent me has inspired me to write a clientless bot :)