@Override
	public byte[] decrypt(byte[] encoded)
	{
		byte[] output = new byte[(int)(Math.ceil(encoded.length / 4.0) * 3)];

		for(int x = 0, y = 0; x < encoded.length - encoded.length % 4; x += 4, y += 3)
		{
			byte a = encoded[x];
			byte b = encoded[x + 1];
			byte c = encoded[x + 2];
			byte d = encoded[x + 3];

			output[y] = (byte)((a << 2 & 0xFC | b >> 4 & 0x03) & 0xFF);
			output[y + 1] = (byte)((b << 4 & 0xF0 | c >> 2 & 0x0F) & 0xFF);
			output[y + 2] = (byte)((c << 6 & 0xC0 | d & 0x3F) & 0xFF);
		}
		byte[] newOutput = null;
		switch(encoded.length % 4)
		{
			case 2:
				newOutput = new byte[output.length - 2];
				System.arraycopy(output, 0, newOutput, 0, newOutput.length);
				output = newOutput;
				output[output.length - 1] = (byte)((encoded[encoded.length - 2] << 2 & 0xFC | encoded[encoded.length - 1] >> 4 & 0x03) & 0xFF);
				break;
			case 3:
				newOutput = new byte[output.length - 1];
				System.arraycopy(output, 0, newOutput, 0, newOutput.length);
				output = newOutput;
				output[output.length - 2] = (byte)((encoded[encoded.length - 3] << 2 & 0xFC | encoded[encoded.length - 2] >> 4 & 0x03) & 0xFF);
				output[output.length - 1] = (byte)((encoded[encoded.length - 2] << 4 & 0xF0 | encoded[encoded.length - 1] >> 2 & 0x0F) & 0xFF);
				break;
		}

		return output;
	}