void BlowFish::InitTables()
	{
	  for ( int tempKey = 0; tempKey < CRYPT_GAMEKEY_COUNT; tempKey++ )
	  {
		memcpy( p_table[tempKey], p_box, sizeof( p_box ) );
		memcpy( s_table[tempKey], s_box, sizeof( s_box ) );

		unsigned char *pAct = key_table[tempKey];
		int j = 0;

		for ( int i = 0; i < 18; i++ )
		{
		  unsigned int mask = 0x00000000;
		  for ( int k = 0; k < 4; ++k )
		  {
			mask = ( mask << 8 ) | *pAct++;
			if ( ++j >= CRYPT_GAMEKEY_LENGTH )
			{
			  j = 0;
			  pAct = key_table[tempKey];
			}
		  }
		  p_table[tempKey][i] ^= mask;
		}

		unsigned int value[2];
		value[0] = value[1] = 0;

		for ( int i = 0; i < 18; i += 2 )
		{
		  RawDecrypt( value, tempKey );
		  p_table[tempKey][i] = value[0];
		  p_table[tempKey][i + 1] = value[1];
		}

		for ( int i = 0; i < 1024; i += 2 )
		{
		  RawDecrypt( value, tempKey );
		  s_table[tempKey][i] = value[0];
		  s_table[tempKey][i + 1] = value[1];
		}
	  }

	  tables_ready = true;
	}
unsigned int ElGamalDecryptor::Decrypt(const byte *cipherText, byte *plainText)
{
	Integer a(cipherText, modulusLen);
	Integer b(cipherText+modulusLen, modulusLen);
	Integer m;

	RawDecrypt(a, b, m);
	m.Encode(plainText, 1);
	unsigned int plainTextLength = plainText[0];
	if (plainTextLength > MaxPlainTextLength())
		return 0;
	m >>= 8;
	m.Encode(plainText, plainTextLength);
	return plainTextLength;
}
	void BlowFish::Decrypt( unsigned char * in, unsigned char * out, int len )
	{
	  if ( stream_pos + len > CRYPT_GAMETABLE_TRIGGER )
	  {
		int len_rem = CRYPT_GAMETABLE_TRIGGER - stream_pos;

		Decrypt( in, out, len_rem );

		table_index = ( table_index + CRYPT_GAMETABLE_STEP ) % CRYPT_GAMETABLE_MODULO;
		memcpy( game_seed, seed_table[1][table_index][0], CRYPT_GAMESEED_LENGTH );
		stream_pos = 0;
		block_pos = 0;

		in += len_rem;
		out += len_rem;
		len -= len_rem;
	  }
	  for ( int tempPos = 0; tempPos < len; tempPos++ )
	  {
		if ( !block_pos )
		{
		  unsigned int values[2];

		  unsigned char *pKey = game_seed;
		  N2L( pKey, values[0] );
		  N2L( pKey, values[1] );

		  RawDecrypt( (unsigned int *)values, table_index );

		  pKey = game_seed;
		  L2N( values[0], pKey );
		  L2N( values[1], pKey );
		}

		block_pos &= 0x07;
		unsigned char c = *in++;
		*out++ = game_seed[block_pos] ^ c;
		game_seed[block_pos] = c;

		block_pos = ( block_pos + 1 ) & 0x07;
	  }

	  stream_pos += len;
	}