[Java] Auth Protocol Cryptographer

03/20/2011 01:34 TomasLT#1
Few month ago i have working AuthProtocolCryptographer but reinstalled win 7 and forgot to save it. And now i cant make new one.
Here is my current one:
Code:
public class AuthCrypto
{
	class CryptCounter
	{
		int m_Counter = 0;

		public byte Key2()
		{
			return (byte)(m_Counter >> 8); 
		}

		public byte Key1()
		{
			return (byte)(m_Counter & 0xFF); 
		}

		public void Increment()
		{
			m_Counter++;
		}
	}

	private CryptCounter _decryptCounter;
	private CryptCounter _encryptCounter;
	private byte[] _cryptKey1;
	private byte[] _cryptKey2;

	public AuthCrypto()
	{
		_decryptCounter = new CryptCounter();
		_encryptCounter = new CryptCounter();
		_cryptKey1 = new byte[0x100];
		_cryptKey2 = new byte[0x100];
		int i_key1 = 0x9D;
		int i_key2 = 0x62;
		for (int i = 0; i < 0x100; i++)
		{
			_cryptKey1[i] = (byte) i_key1;
			_cryptKey2[i] = (byte) i_key2;
			i_key1 = (byte)((0x0F + (byte)(i_key1 * 0xFA)) * i_key1 + 0x13);
			i_key2 = (byte)((0x79 - (byte)(i_key2 * 0x5C)) * i_key2 + 0x6D);
		}
	}

	public void Decrypt(byte[] buffer)
	{
		for (int i = 0; i < buffer.length; i++)
		{
			buffer[i] ^= (byte)0xAB;
			buffer[i] = (byte)(buffer[i] >> 4 | buffer[i] << 4);
			buffer[i] ^= (byte)(_cryptKey1[_decryptCounter.Key1()] ^ _cryptKey2[_decryptCounter.Key2()]);
			_decryptCounter.Increment();
		}
	}
	public void Encrypt(byte[] buffer)
	{
		for (int i = 0; i < buffer.length; i++)
		{
			buffer[i] ^= (byte)0xAB;
			buffer[i] = (byte)(buffer[i] >> 4 | buffer[i] << 4);
			buffer[i] ^= (byte)(_cryptKey1[_encryptCounter.Key1()] ^ _cryptKey2[_encryptCounter.Key2()]);
			_encryptCounter.Increment();
		}
	}

	public void EncryptBackwards(byte[] buffer)
	{
		for (int i = 0; i < buffer.length; i++)
		{
			buffer[i] ^= (byte)(_cryptKey2[_encryptCounter.Key2()] ^ _cryptKey1[_encryptCounter.Key1()]);
			buffer[i] = (byte)(buffer[i] >> 4 | buffer[i] << 4);
			buffer[i] ^= (byte)0xAB;

			_encryptCounter.Increment();
		}
	}
	public void DecryptBackwards(byte[] buffer)
	{
		for (int i = 0; i < buffer.length; i++)
		{
			buffer[i] ^= (byte)(_cryptKey2[_decryptCounter.Key2()] ^ _cryptKey1[_decryptCounter.Key1()]);
			buffer[i] = (byte)(buffer[i] >> 4 | buffer[i] << 4);
			buffer[i] ^= (byte)0xAB;

			_decryptCounter.Increment();
		}
	}

	public void GenerateKeys(int CryptoKey, int AccountID)
	{
		int tmpkey1 = 0, tmpkey2 = 0;
		tmpkey1 = ((CryptoKey + AccountID) ^ (0x4321)) ^ CryptoKey;
		tmpkey2 = tmpkey1 * tmpkey1;

		for (int i = 0; i < 256; i++)
		{
			int right = ((3 - (i % 4)) * 8);
			int left = ((i % 4)) * 8 + right;
			_cryptKey1[i] ^= (byte)(tmpkey1 << right >> left);
			_cryptKey2[i] ^= (byte)(tmpkey2 << right >> left);
		}
	}
}
but it cant de/en correctly and dont know why? de/en changed in last months ? or i have made mistakes in my class ?


Here how i use it:
Code:
import java.io.*;
import java.net.*;
public class proxy {

	public static void main(String[] args) throws Exception {
		String AuthIP = "208.96.34.46";
		int port = 9960;
		/*
		// TEST PURPOSE
		AuthCrypto ac = new AuthCrypto();
		byte[] buff = {0xC5,(byte)0x48,(byte)0x69,(byte)0x12,(byte)0x04,(byte)0x85,(byte)0xF5,(byte)0xEA};
		ac.DecryptBackwards(buff);
		Print("Test : ",buff);
		*/
		
		ServerSocket SS = new ServerSocket(9960);
		Socket Client = SS.accept();
		if(Client.isConnected()==true){	
			System.out.println("Client Connected to proxy !");
			Socket Auth = new Socket(AuthIP,9960);
			DataInputStream fromAuth = new DataInputStream(Auth.getInputStream());
			DataInputStream fromClient = new DataInputStream(Client.getInputStream());
			DataOutputStream toClient = new DataOutputStream(Client.getOutputStream());
			DataOutputStream toAuth = new DataOutputStream(Auth.getOutputStream());
			
			AuthCrypto crypt = new AuthCrypto();
			
			if(Auth.isConnected()== true){
				System.out.println("Connected to "+AuthIP+" at port "+port);
				byte buffer[] = new byte[8];
				fromAuth.read(buffer, 0, 8);
				Print("From Auth : ",buffer);
				toClient.write(buffer);
				buffer = new byte[276];
				fromClient.readFully(buffer);
				Print("from Client : ",buffer);
				toAuth.write(buffer, 0, buffer.length);
				buffer = new byte[52];
				fromAuth.readFully(buffer, 0, buffer.length);
				Print("Original  : ",buffer);
				crypt.DecryptBackwards(buffer);
				Print("Decrypted : ",buffer);
				crypt.Encrypt(buffer);
				Print("Encrypted : ",buffer);
                               
			       
			}
			Auth.close();
		}
	}
	public static String toHex(byte b) {
		  String result = "";
		  result =Integer.toString( ( b & 0xff ) + 0x100, 16).substring(1);
		  return result;
	}
	public static void Print(String text,byte[] buffer) throws Exception
	{
		System.out.print(text);
		for (int i = 0; i < buffer.length; i++)
		{
			System.out.print(toHex(buffer[i]).toUpperCase()+" ");
		}
		System.out.println("");
	}
}
03/20/2011 03:00 shitboi#2
it did not change. java primitive types are signed, and there is no way for you to declare them as unsigned. However this auth cryptographer uses unsigned types. Hint: use &0xff after bit-wise operations.
03/20/2011 15:48 ImFlamedCOD#3
[Only registered and activated users can see links. Click Here To Register...].

That is the project called Jonquer. It was founded by ChingChong and was a original public java proxy source. It was quite well coded and a good base proxy. Not a single person here took interest in it but the project is still hosted on Google Code. Take a look at it should be able to help you.
03/20/2011 15:50 iStefan#4
This is Java??
Seems easier than I thought lol.
03/20/2011 16:13 TomasLT#5
link dont works for me!

Edited:
oh the real link is [Only registered and activated users can see links. Click Here To Register...]
03/20/2011 17:29 ImFlamedCOD#6
Java is a nice language it has its up and downs just like any other language. Rather to taken to the programmer who is using the language to code something. Java is one of the most versatile languages out there being multipliable platform , and on top of being a widely used language. Tho i prefer c++ myself, now and days Java is still one of the ones to be used for commercial and personal use world wide. I think its great that people are exploring langues and committing for help here on ElitePvpers where help and guidance seems to be lacking. I am glad i could have helped you and i wish you luck in your Java journey. Keep this thread posted on progress your having and ask questions that you do not know or answers you have yet to find. Believe it or not some people here have Java experience and would most likely be glad to help you. This end InFlamedCOD's commission's of wisdom.
03/20/2011 19:06 TomasLT#7
Quote:
Originally Posted by ImFlamedCOD View Post
Java is a nice language it has its up and downs just like any other language. Rather to taken to the programmer who is using the language to code something. Java is one of the most versatile languages out there being multipliable platform , and on top of being a widely used language. Tho i prefer c++ myself, now and days Java is still one of the ones to be used for commercial and personal use world wide. I think its great that people are exploring langues and committing for help here on ElitePvpers where help and guidance seems to be lacking. I am glad i could have helped you and i wish you luck in your Java journey. Keep this thread posted on progress your having and ask questions that you do not know or answers you have yet to find. Believe it or not some people here have Java experience and would most likely be glad to help you. This end InFlamedCOD's commission's of wisdom.
Nice speach. But i really have problems. I`m so stupid ? my ide is stupid or ... ?
Code:
 import java.nio.*;
public class AuthCrypto {

    private static final byte[] cryptKey1;
    private static final byte[] cryptKey2;
    public int lastLength = 0;

    static {
	cryptKey1 = new byte[0x100];
	cryptKey2 = new byte[0x100];
	byte iKey1 = (byte) 0x9d;
	byte iKey2 = 0x62;
	for (int i = 0; i < 0x100; i++) {
	    cryptKey1[i] = iKey1;
	    cryptKey2[i] = iKey2;
	    iKey1 = (byte) ((0x0f + (byte) (iKey1 * 0xfa)) * iKey1 + 0x13);
	    iKey2 = (byte) ((0x79 - (byte) (iKey2 * 0x5c)) * iKey2 + 0x6d);
	}
    }

    private byte[] cryptKey3;
    private byte[] cryptKey4;
    private boolean alternate;
    public int in;
    private int out;

    public void generateKeys(int token, int accountId) {
	cryptKey3 = new byte[0x100];
	cryptKey4 = new byte[0x100];
	int tmpKey1 = ((accountId + token) ^ 0x4321) ^ accountId;
	int tmpKey2 = tmpKey1 * tmpKey1;
	byte[] tmp1 = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(tmpKey1).array();
	byte[] tmp2 = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(tmpKey2).array();
	for (int i = 0; i < 0x100; i++) {
	    cryptKey3[i] = (byte) (cryptKey1[i] ^ tmp1[i % 4]);
	    cryptKey4[i] = (byte) (cryptKey2[i] ^ tmp2[i % 4]);
	}
	out = 0;
	alternate = true;
    }

    public void encrypt(byte[] packet) {
	for (int i = 0; i < packet.length; i++) {
	    packet[i] = (byte) ((packet[i] & 0xff) ^ 0xab);
	    packet[i] = (byte) (((packet[i] & 0xff) << 4) | ((packet[i] & 0xff) >> 4));
	    packet[i] = (byte) (cryptKey2[(out >> 8) & 0xff] ^ (byte)(packet[i] & 0xff));
	    packet[i] = (byte) (cryptKey1[out & 0xff] ^ (packet[i] & 0xff));
	    out++;
	}
    }

    public void encrypt(ByteBuffer packet) {
	for (int i = 0; i < packet.remaining(); i++) {
	    packet.put(i, (byte) ((packet.get(i) & 0xff) ^ 0xab));
	    packet.put(i, (byte) (((packet.get(i) & 0xff) << 4) | ((packet.get(i) & 0xff) >> 4)));
	    if (alternate) {
		packet.put(i, (byte) (cryptKey4[in >> 8] ^ (packet.get(i) & 0xff)));
		packet.put(i, (byte) (cryptKey3[in & 0xff] ^ (packet.get(i) & 0xff)));
	    } else {
		packet.put(i, (byte) (cryptKey2[in >> 8] ^ (packet.get(i) & 0xff)));
		packet.put(i, (byte) (cryptKey1[in & 0xff] ^ (packet.get(i) & 0xff)));
	    }
	    this.in++;
	}
    }
    public void decrypt(ByteBuffer packet) {
    	for (int i = 0; i < packet.remaining(); i++) {
    		packet.put(i, (byte) (cryptKey1[in & 0xff] ^ (packet.get(i) & 0xff)));
    		packet.put(i, (byte) (cryptKey2[in >> 8] ^ (packet.get(i) & 0xff)));
    		if (alternate) { 
    			packet.put(i, (byte) (cryptKey3[in & 0xff] ^ (packet.get(i) & 0xff)));
    			packet.put(i, (byte) (cryptKey4[in >> 8] ^ (packet.get(i) & 0xff)));
    		} else {
    			packet.put(i, (byte) (((packet.get(i) & 0xff) << 4) | ((packet.get(i) & 0xff) >> 4)));
    			packet.put(i, (byte) ((packet.get(i) & 0xff) ^ 0xab));
    	    }
    	    this.in++;
    	}
    }
}
here i used "& 0xff" after bit-wise operations, but everytime results is the same.

Waiting for ur answer guys. Glad that there is people who want to help.
03/21/2011 03:10 shitboi#8
Quote:
Originally Posted by ImFlamedCOD View Post
[Only registered and activated users can see links. Click Here To Register...].

That is the project called Jonquer. It was founded by ChingChong and was a original public java proxy source. It was quite well coded and a good base proxy. Not a single person here took interest in it but the project is still hosted on Google Code. Take a look at it should be able to help you.
That thank is for sharing codes with everyone, lol.

Anyway, I had chingchong on msn, and he sent the entire bundle to me when i was struggling with my blowfishcfb64. This project is really well structured, it totally put my proxy to utter shame.

@thomas, I am pretty sure i have sent my log in cipher to you months ago, and you got it working. I am a bit disappointed that you didn't dig the source repository hard enough, else you'd have found your answer.

Anyway, this is the explanation to your problem.

since java only have signed variables, values represented by a byte is from -128 to +127

Let's take 199 as an example. convert this byte to bits, we get 1100 0111. Since java is signed, the first bit on the left is understood as sign bit. And 1100 0111 will be treated as a 2's complement representation. So, hte value of 1100 0111 will be complement(1100 0111 - 1) = 0011 1001 = -57

Think about it, this is actually the amount overflowed; 256(size of byte) -57 = 199. Alright, enough of the technical part, to the practical part.

In bitwise operations, Eg:
(unsigned) 1100 0111 >> 4 = 0000 1100
(signed) 1100 0111 >> 4 = 1000 1100 //sign bit preserved.

Clearly you can see both binary numbers mean very different things.
To rectify your problem, you should have done either of the following

( byte_var >> n ) & 0xf <-- this only applies to a right shift of 4 bits on byte variables
proof: 1000 1100 & 0000 1111 = 0000 1100 (same as the unsigned right shift by 4 bits.
OR
byte_var >>> n

Edit:
If you really want to learn, i suggest you not directly qouting codes from Xent's project. That one is very complicated. And if you look harder, he is using NIO, that is on a different level from simple ServerSocket library that you will need. (i wont go deeper to reason it out, just to let you know, i am using ServerSocket)

Why not start from the basics, You can refer to project alchemy, copy the codes, paste the codes into your java IDE, edit the syntax's a bit, handle the bitwise operation errors, and the OLD structure you showed me months ago WILL work.
03/21/2011 10:46 TomasLT#9
@shitboi: i lost my old source. So i writing it from scrach. And i try to use project alchemy source but everythime i get the same result. ANuway i will try it again later.

Code:
public void DecryptBackwards(byte[] buffer)
    {
        for (int i = 0; i < buffer.length ; i++)
        {
        	buffer[i] ^= (byte)(_cryptKey2[_decryptCounter.Key2()] ^ _cryptKey1[_decryptCounter.Key1()]);
        	buffer[i] = (byte) (((buffer[i] & 0xFF) >> 4) & 0xFF | ((buffer[i] & 0xFF) << 4) & 0xFF);
            buffer[i] = (byte)(((buffer[i] & 0xFF) ^ 0xAB) & 0xFF) ;
            _decryptCounter.Increment();
        }
    }
i read lots explanation about unsigned bytes, bitwise operations in java but cant undestand what i`m doing wrong.

Code:
((buffer[i] & 0xFF) >> 4 ) & 0xFF
So i still mist something ?
03/21/2011 15:55 shitboi#10
byte( ( buffer[i] >> 4 ) & 0xFF) shall do the trick in all instances of right shift

Again, you should sit down and work out why this should be done in such a way. If you do not understand this, it's hard for you to move on to the later part of proxy development.
03/21/2011 16:36 TomasLT#11
SO but this code dont fix it
Code:
public void DecryptBackwards(byte[] buffer)
    {
        for (int i = 0; i < buffer.length ; i++)
        {
        	buffer[i] ^= (byte)(_cryptKey2[_decryptCounter.Key2()] ^ _cryptKey1[_decryptCounter.Key1()]);
        	buffer[i] = (byte) ((buffer[i]  >> 4) & 0xFF | (buffer[i]  << 4) & 0xFF);
            buffer[i] = (byte)((buffer[i]) ^ 0xAB) & 0xFF) ;
            _decryptCounter.Increment();
        }
    }
03/21/2011 16:46 shitboi#12
That is why i said you need to sit down and try to understand. you dont need to do an AND for OR operations, Also, have you checked the m_counter function?

Code:
    public void Decrypt(byte[] buffer) {
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] ^= (byte) (_cryptKey1[_encryptCounter.getKey1()] ^ _cryptKey2[_encryptCounter.getKey2()]);
            buffer[i] = (byte) ( ((buffer[i] >> 4)&0xf) | buffer[i] << 4);
            buffer[i] ^= (byte) 0xAB;
            _encryptCounter.Increment();
        }
    }
This is the code for decrypting packet from server. You need to double check your cryptcounter and constructor and make sure your byte casts are proper, any right shift operations are taken care of. Also, you need to make sure you are using the correct decrypt/encrypt method for the right task, and you should be good to go. This would be all my input on this topic, good luck.
03/21/2011 17:11 TomasLT#13
at last i fixed it. Just u mislead me when u said that i need to use & 0xff
And here is the full working auth class in java is some1 need it:
Code:
public class AuthProtocolCryptographer
{
    class CryptCounter
    {
        byte m_Counter = 0x00;

        public byte Key2()
        {
            	return  (byte)((m_Counter >> 8) & 0xF); 
        }

        public byte Key1()
        {
        		return (byte) (m_Counter & 0xFF); 
        }

        public void Increment()
        {
            m_Counter++;
        }
    }

    private CryptCounter _decryptCounter;
    private CryptCounter _encryptCounter;
    private byte[] _cryptKey1 ;
    private byte[] _cryptKey2;
    
    public AuthProtocolCryptographer()
    {
        _decryptCounter = new CryptCounter();
        _encryptCounter = new CryptCounter();
        _cryptKey1 = new byte[0x100] ;
        _cryptKey2 = new byte[0x100];
        byte i_key1 = (byte) 0x9D;
        byte i_key2 = 0x62;
        for (int i = 0; i < 0x100; i++)
        {
            _cryptKey1[i] = i_key1;
            _cryptKey2[i] = i_key2;
            i_key1 = (byte) ((0x0f + (byte) (i_key1 * 0xfa)) * i_key1 + 0x13);
    	    i_key2 = (byte) ((0x79 - (byte) (i_key2 * 0x5c)) * i_key2 + 0x6d);
        }
    }

    public void Decrypt(byte[] buffer)
    {
        for (int i = 0; i < buffer.length; i++)
        {
        	buffer[i] ^= (byte)0xAB ;
            buffer[i] = (byte) ((buffer[i] >> 4) & 0xF | (buffer[i] << 4));
            buffer[i] ^= (byte)(_cryptKey1[_decryptCounter.Key1()] ^ _cryptKey2[_decryptCounter.Key2()]);
            _decryptCounter.Increment();
        }
    }
    public void Encrypt(byte[] buffer)
    {
        for (int i = 0; i < buffer.length; i++)
        {
        	buffer[i] ^= (byte)0xAB ;
            buffer[i] = (byte)((buffer[i] >> 4) & 0xf | buffer[i] << 4);
            buffer[i] ^= (_cryptKey1[_encryptCounter.Key1()] ^ _cryptKey2[_encryptCounter.Key2()]);
            _encryptCounter.Increment();
        }
    }

    public void EncryptBackwards(byte[] buffer)
    {
        for (int i = 0; i < buffer.length; i++)
        {
            buffer[i] ^= (byte) (_cryptKey2[_encryptCounter.Key2()] ^ _cryptKey1[_encryptCounter.Key1()]);
            buffer[i] = (byte) ((buffer[i] >> 4) &0xf | (buffer[i] << 4));
            buffer[i] ^= (byte) 0xAB  ;
            _encryptCounter.Increment();
        }
    }
    public void DecryptBackwards(byte[] buffer)
    {
        for (int i = 0; i < buffer.length ; i++)
        {
        	buffer[i] ^= (byte)(_cryptKey2[_decryptCounter.Key2()] ^ _cryptKey1[_decryptCounter.Key1()]);
        	buffer[i] = (byte) ((buffer[i] >> 4) & 0xF | (buffer[i] << 4));
            buffer[i] ^= (byte) (0xAB) ;
            _decryptCounter.Increment();
        }
    }

    public void GenerateKeys(byte CryptoKey, byte AccountID)
    {
        int tmpkey1 = 0, tmpkey2 = 0;
        tmpkey1 = ((CryptoKey + AccountID) ^ (0x4321)) ^ CryptoKey;
        tmpkey2 = tmpkey1 * tmpkey1;

        for (int i = 0; i < 256; i++)
        {
            byte right = (byte) ((3 - (i % 4)) * 8);
            byte left = (byte) (((i % 4)) * 8 + right);
            _cryptKey1[i] ^= (tmpkey1 & 0xFF << right >>> left);
            _cryptKey2[i] ^= (tmpkey2 & 0xFF << right >>> left);
        }
    }
}