Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 3 of 3

Thread: XOR encryption algorithm code clean-up

  1. #1
    Member
    Join Date
    Feb 2012
    Posts
    173
    Thanks
    6
    Thanked 10 Times in 10 Posts

    Default XOR encryption algorithm code clean-up

    I wrote a XOR encryption algorithm that ended up taking up a lot of code. It works (I tested it with Project Euler problem 59) and encrypts/decrypts accurately. It encrypts character in UTF-8 to keep the program simple. However, I don't know how much of the code I wrote is need and not already available some other java class.

    package algorithms;
     
    public class Encryptor {
     
    	int length = 0;
    	/**
    	 * XOR encryptor
    	 */
     
    	public Encryptor(){}
     
    	/**
    	 * @param message - the message to be encrypted
    	 * @param key - password for encryption
    	 * @return the encrypted message
    	 */
    	public String encrypt(String message, String key)
    	{
    		String enc = "";//String that will contain the encrypted message
    		length = message.length();//length of the message
    		String[] mess = toArray(message);//Binary values of every character in the message
    		String[] key1 = makeKey(toArray(key));//Binary values of the characters in the key repeated to the required length if needed
    		for(int i = 0; i < length; i++)//loop to add each encrypted character to enc
    		{			
    			enc+=String.valueOf((char)binaryTobyte(binaryAdd(mess[i], key1[i])));
    		}
     
    		return enc;//encrypted message
    	}
     
    	/**
    	 * @param str - String to be made into a String[] of binary values
    	 * @return - String[] of the binary representatino of every letter in String str
    	 */
    	private String[] toArray(String str)
    	{
    		String[] bin = new String[str.length()];//array that will conatin the binary values of every character in str
    		byte[] vals = str.getBytes();//the byte vales of the message, synonymous the the char value of each letter
     
    		for(int i = 0; i < bin.length; i++)//loop adding the binary translation of every letter to the bin array
    		{
    			bin[i] = toBinary(vals[i]);
    		}
     
    		return bin;
    	}
     
    	/**
    	 * @param arr - Binary String[] of the key
    	 * @return - Returns the Binary key, the array returned represents the letters in the key, translated to binary, and then repeated to the length of the message to be encrypted
    	 * Should be ran after the toArray method with the array from that method.
    	 */
    	private String[] makeKey(String[] arr)
    	{
    		String[] key = new String[length];//String[] that will contain the repeated, if necessary, binary values for each character in the key
    		int ind = 0;//indexes arr
    		for(int i = 0; i < length; i++)//loop to fill key[]
    		{
    			if(ind >= arr.length)//resets ind if greater than the number of values in arr
    			{
    				ind = 0;
    			}
    			key[i] = arr[ind];
    			ind++;
    		}
     
    		return key;
    	}
     
    	/**	
    	 * @param bin1 - String containing a binary value
    	 * @param bin2 - String containing another binary value;
    	 * @return an array of the combined binary String values
    	 * @throws Throws an exception if either String is not binary.
    	 */
    	private byte[] binaryAdd(String bin1, String bin2)
    	{
    		byte[] sum;//array that will contain the combined bin1 and bin2
     
    		if(bin1.contains("2")||bin1.contains("3")||bin1.contains("4")||bin1.contains("5")||bin1.contains("6")||bin1.contains("7")||bin1.contains("8")||bin1.contains("9"))
    		{
    			throw new IllegalArgumentException("Argument not binary.");
    		}
    		if(bin2.contains("2")||bin2.contains("3")||bin2.contains("4")||bin2.contains("5")||bin2.contains("6")||bin2.contains("7")||bin2.contains("8")||bin2.contains("9"))
    		{
    			throw new IllegalArgumentException("Argument not binary.");
    		}
     
    		if(bin1.length()>=bin2.length())//makes the array equal to the longest String of binary values
    		{
    			sum = new byte[bin1.length()];
    		}
    		else
    		{
    			sum = new byte[bin2.length()];
    		}
     
    		for(int i = 0; i < sum.length; i++)//combines each bit and adds it to the sum array
    		{
    			byte a = Byte.parseByte(bin1.substring(i, i+1));
    			byte b = Byte.parseByte(bin2.substring(i, i+1));
    			if(a == b)// 0 -> 0 = 0     &     1 -> 1 = 0    in binary
    			{
    				sum[i]=0;
    			}
    			else// 1 -> 0 = 1		&		0 -> 1 = 1		in binary
    			{
    				sum[i]=1;
    			}	
    		}
    		return sum;
    	}
     
    	/**
    	 * @param num - byte value to be converted to an int value
    	 * @return The absolute value of the byte value 'num'
    	 */
    	private int toInt(byte num)
    	{
    		return Math.abs(Integer.parseInt(Byte.toString(num)));//question here: When testing Byte.toString(), I found that the value 128 when put into that method, Byte.toString(), returns as -128 and messed up the values. Why does Byte.toString((byte) 128) = "-128"?
    	}
    	/**
    	 * @param num - byte value to be made binary
    	 * @return String containing the binary translation of value num, length % 8 always equals 0.
    	 */
    	private String toBinary(byte num)
    	{
    		String bin = Integer.toBinaryString(toInt(num));//takes num and makes it inter an integer and then into a Binary String.
     
    		while(bin.length()%8!=0)//if the length is not 8, 16, 24, 32, etc... evenly divisible by eight, adds 0's to the front
    		{
    			bin = "0".concat(bin);
    		}
     
    		return bin;
    	}
    	/**
    	 * @param bin - binary byte[] to be translated the a non-binary number
    	 * @return the byte value of bin
    	 */
    	private byte binaryTobyte(byte[] bin)
    	{
    		byte num = 0;//variable that will contain the 8-bit translation of the argument array
    		int exp = bin.length-1;//starts at the length of the array - 1 because the first value in a binary number is 2^0. If you are confused, look it up.
    		for(int i = 0; i < bin.length; i++)//loop to add values of the 1's to num.
    		{
    			if(bin[i]==1)
    			{
    				num+=Math.pow(2, exp);
    			}
    			exp--;
    		}
     
    		return num;
    	}
     
     
    	public static void main(String[] args)
    	{}
    }

    The program runs perfectly, I haven't benchmarked it to see how fast it is able to encrypt, but I know it's accurate. This program is not optimized, so optimizations are welcome.


  2. #2
    Member
    Join Date
    Jun 2012
    Location
    Left Coast, USA
    Posts
    451
    My Mood
    Mellow
    Thanks
    1
    Thanked 97 Times in 88 Posts

    Default Re: XOR encryption algorithm code clean-up

    Quote Originally Posted by aesguitar View Post
    I wrote a XOR encryption algorithm that ended up taking up a lot of code...
    I can't see any reason for convert back and forth from chars to "binary strings" and doing all of that other conversion into bits, "adding" binary strings (actually your "add" function does a bit-by-bit exclusive-or) etc...


    Why not just operate on the bytes directly? I mean, the encryption is a simple byte-by-byte XOR, right? Just do it!

    I added the following inside your class definition and didn't change anything else:

        //
        // Input: message and key strings.
        // Encrypted result returned as an array of ints.
        //
        //   Zaphod_b
        //
        public int [] enc(String msg, String key)
        {
            int [] ret = new int[msg.length()];
            int m = key.length();
            for (int i = 0; i < msg.length(); i++)
            {
                ret[i] = (int)msg.charAt(i) ^ (int)key.charAt(i%m);
            }
            return ret;
        } // End of enc()
     
     
        public static void main(String [] args)
        {
            Encryptor encryptor = new Encryptor();
            String key = "abc";
            String message = "The quick brown fox jumps over the lazy dog.";
     
            System.out.println("Message: " + message);
            System.out.println("Key    : " + key);
            System.out.println();
     
            System.out.println("First line is from original encrypt(), second from smaller enc():");
     
            String encrypted = encryptor.encrypt(message, key);
            for (int i = 0; i < encrypted.length(); i++)
            {
                System.out.print((int)encrypted.charAt(i));
                if (i < encrypted.length()-1)
                {
                    System.out.print(",");
                }
                else
                {
                    System.out.println();
                }
            }
     
            int [] e = encryptor.enc(message, key);
            for (int i = 0; i < e.length; i++)
            {
                System.out.print(e[i]);
                if (i < e.length-1)
                {
                    System.out.print(",");
                }
                else
                {
                    System.out.println();
                }
            }
            System.out.println();
        } // End of main()
    }

    This prints encoded bytes as a comma-separated list of decimal integer values like the encrypted file used for the Project Euler problem.

    Output:
    Message: The quick brown fox jumps over the lazy dog.
    Key    : abc
     
    First line is from original encrypt(), second from smaller enc():
    53,10,6,65,19,22,8,1,8,65,0,17,14,21,13,65,4,12,25,66,9,20,15,19,18,66,12,23,7,17,65,22,11,4,66,15,0,24,26,65,6,12,6,76
    53,10,6,65,19,22,8,1,8,65,0,17,14,21,13,65,4,12,25,66,9,20,15,19,18,66,12,23,7,17,65,22,11,4,66,15,0,24,26,65,6,12,6,76



    A decryption function that takes an array of ints (no commas) and returns a String could go like this:
        String dec(int [] encmsg, String key)
        {
            String ret = "";
     
            // Step through encmsg byte by byte, xoring with key chars modulo key length
            for (int i = 0; i < e.length; i++)
            {
                ret += blah-blah-blah
            }
     
            return ret;
        } // End of dec()

    Then it would be called like this:
            // e is an array of ints, key is a String.
            String recovered = encryptor.dec(e, key);
            System.out.println("Recovered message: " + recovered);

    The enc() and dec() functions are mathematically symmetrical (same algorithm encrypts and decrypts), input parameters and return types (and the judicious casting that makes the operations compatible) are the only difference.


    Cheers!


    Z
    Last edited by Zaphod_b; August 1st, 2012 at 11:55 PM.

  3. #3
    Member
    Join Date
    Feb 2012
    Posts
    173
    Thanks
    6
    Thanked 10 Times in 10 Posts

    Default Re: XOR encryption algorithm code clean-up

    That's originally how I did it, but I wasn't getting accurate decryptions. That's when I did a little research and questioning my mom (she knows more than I do about cryptology) and that's when I decided to go with calculating each bit in each letter approach. I can use the same method to encrypt and decrypt.

    say that :
     {0,1,1,0,0,1,0,1}
    is the binary value of a character in the message, and
     {1,0,0,1,1,1,0,0}
    is the bit value of a character in the key.

    When the encryption runs:

    {0,1,1,0,0,1,0,1}
    {1,0,0,1,1,1,0,0}
    =============
    {1,1,1,1,1,0,0,1} would be the encrypted value.

    The good thing about my method, is that if you take the encrypted value and run it through the algorithm again with the same key, you get the plain text message. It just seemed easier to me. Let me rephrase my original question; Are there any classes I could import to do the binary translation for me?

Similar Threads

  1. What makes a "good" encryption algorithm?
    By aesguitar in forum Java Theory & Questions
    Replies: 3
    Last Post: July 11th, 2012, 06:14 PM
  2. java code for chameleon clustering algorithm
    By draksha in forum Java Theory & Questions
    Replies: 2
    Last Post: August 11th, 2011, 07:55 AM
  3. Java code for Leader's algorithm
    By raj_k in forum Member Introductions
    Replies: 1
    Last Post: August 9th, 2011, 06:20 AM
  4. Trying to clean this part of my progam up, but cant seem to get it.
    By Mob31 in forum What's Wrong With My Code?
    Replies: 5
    Last Post: February 25th, 2011, 03:49 PM
  5. Please help me clean up my code!
    By Java Neil in forum What's Wrong With My Code?
    Replies: 8
    Last Post: February 25th, 2011, 01:48 PM