-1

I have some trouble in encrypting and decrypting some AES messages because of byte[]-String conversions...I find quite interesting how a[9]!=c[9] (saw the difference when debugging)

try {

        String encryptionKey = "1234567890123456";
        String plaintext = "1234567890123456";

        System.out.println("key:   " + encryptionKey);
        System.out.println("plain:   " + plaintext);
        byte[] a = aes.encrypt(plaintext, encryptionKey);
        String b = new String(a);
        byte[] c = b.getBytes();

        String decrypted = new String(aes.decrypt(c, encryptionKey));

        System.out.println("decrypt: " + decrypted);

    } catch (Exception e) {
      e.printStackTrace();
    } 
}


public byte[] encrypt(String plainText, String encryptionKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes(), "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes()));
    return cipher.doFinal(plainText.getBytes());
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Andrew M.
  • 15
  • 1
  • 1
  • 8
  • A byte is 8 bits. A Java `char` is 16 bits. When you convert arbitrary 8-bit-byte arrays to Java Strings (or vice-versa) you're generally going to encounter some "mapping" as the 8-bit data will be interpreted as UTF8 or some other character encoding where bytes > 127 are regarded as special characters and expanded somehow. If you want to transmit "pure binary" (and encrypted data is generally "pure binary") as a String you need to use Base64 encoding or some such. – Hot Licks Apr 26 '13 at 15:31
  • @Fildor if I use:String decrypted = new String(aes.decrypt(c, encryptionKey)); the result will be:key: 1234567890123456 plain: 1234567890123456 decrypt: ń?Ľ·w?q9rÁK?y – Andrew M. Apr 26 '13 at 15:36
  • Have you tried using UTF-8 encoding? – Fildor Apr 26 '13 at 15:43
  • Take a look at this. http://stackoverflow.com/questions/16232023/java-byte-to-from-string-conversion – MosesA Apr 26 '13 at 15:43
  • possible duplicate of [what is character encoding](http://stackoverflow.com/questions/10611455/what-is-character-encoding) – Raedwald Apr 10 '15 at 11:53

2 Answers2

0

Actually I want to send the data over a TCP connection as follow, but still have some problem... I compared the string sent by the server with the string received by client and they DO NOT match

The server lookes like:

public class server {
static String aeskey;
static String secret;
public static void main(String[] args) throws Exception {

AES aes = new AES();

    ServerSocket serverSocket = null;
    try {
        serverSocket = new ServerSocket(1234);
    } catch (IOException e) {
        System.err.println("Could not listen on port: 1234.");
        System.exit(1);
    }

    Socket clientSocket = null;
    try {
        clientSocket = serverSocket.accept();
    } catch (IOException e) {
        System.err.println("Accept failed.");
        System.exit(1);
    }

    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    String int1,int2;

byte[] cipher = aes.encrypt("1234567890123456", "1234567890123456");
String s = new String(cipher , "ISO-8859-1");
out.println(s);

int1 = in.readLine();
System.out.println("From Client:"+int1);


    out.close();
    in.close();
    clientSocket.close();
    serverSocket.close();
}
}

And the client (tried in Android) looks as follow:

public class MainActivity extends Activity {

int cmd, ret;
public String IPAdress;
public String aeskey;
public String secret;
public Socket socket;
public PrintWriter out;
public BufferedReader in;
public AES aes = new AES();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final Button b1 = (Button)findViewById(R.id.button1);

    cmd = 0;
    b1.setText("Connect to server");

    b1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(cmd == 0) ////setting-up the connection
            {
                int cs = connect_to_server();
                if(cs == 0)
                {
                    b1.setText("Connected");
                    try {
                        int dp  = do_protocol();
                    } catch (UnsupportedEncodingException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    cmd = 1;
                    }
            }
            else 
            {
                ///to be edited later
            }
        }
    });

}

public int do_protocol() throws UnsupportedEncodingException
{
    int d = 0;
    BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
    String num1 = null,num2 = null;

    aeskey=aes.generateRandomString(16); ///generez o cheie AES

    try {
        num1 = in.readLine();
    } catch (IOException e1) {
        d = 1;
        e1.printStackTrace();
    }

    byte[] cipher = null;
    cipher = num1.getBytes("ISO-8859-1");
    try {
        num2 = new String(aes.decrypt(cipher, aeskey));
    } catch (Exception e) {
        d = 2;
        e.printStackTrace();
    }
    out.println(num2);

    return d;
}

public int connect_to_server()
{
    ret = 0;
    try {
        socket = new Socket("192.168.1.144", 1234);
        out = new PrintWriter(socket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    } catch (UnknownHostException e) {
        Toast.makeText(this, "Unable to connect to server", Toast.LENGTH_LONG).show();
        ret = 1;
        } catch (IOException e) {
        Toast.makeText(this, "Unable to connect to server", Toast.LENGTH_LONG).show();
        ret = 2;
        }
    if(ret == 0)
        Toast.makeText(this, "Connected to server", Toast.LENGTH_LONG).show();
    return ret;
}
Andrew M.
  • 15
  • 1
  • 1
  • 8
  • I have compared server`s "cipher" with client`s "cipher" and they differ only at negative value position; client`s "cipher" being all-positive :( Some suggestions? – Andrew M. Apr 27 '13 at 06:59
  • @PeterLawrey so how am I supposed to send/receive it? – Andrew M. Apr 27 '13 at 10:06
  • If you are transmitting a `byte[]` directly you must send with a binary protocol. If you are transmitting a `String` or `char[]` you must translate the `byte[]` output from the encryption into Base64 (or some other such representation). – Hot Licks Apr 27 '13 at 11:37
-1

This only works for byte[] which contains bytes which are correct for your default encoding. e.g. say it is windows-1251, or UTF-8 then most ASCII 0-127 bytes are okay but byte above this will get mangled or translated to ?

String b = new String(a);
byte[] c = b.getBytes();

Try instead

String b = new String(a, "ISO-8859-1");
byte[] c = b.getBytes("ISO-8859-1");

The "ISO-8859-1" encoding translates 0-255 to 0-255 so preserves you original information.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • But that is not the way to transmit binary data. Send it out on the network and it will be hopelessly garbled. – Hot Licks Apr 26 '13 at 16:22
  • @HotLicks Sometimes all you want to do is print the binary so you can get a sense of what it is doing. He isn't trying to send it over a network but with ISO-8859-1 it won't get garbled as I have already explained. – Peter Lawrey Apr 26 '13 at 17:59
  • Yes, but it won't print either. – Hot Licks Apr 26 '13 at 18:06
  • @HotLicks It will print, but many of the characters won't make sense. Some control characters won't not do what you expect. However, redirect the output to a file and it can be exactly the same as if you wrote it in binary. – Peter Lawrey Apr 26 '13 at 21:36
  • @PeterLawrey I have posted bellow the context in which I am using the code...still have the same problem, sort of. – Andrew M. Apr 27 '13 at 04:07
  • The simplest thing to do is to send binary as binary. You can send it as text if you are very careful and use ISO-8859-1 but if you only want to send binary, just do that. BTW This is what Sockets do by default. – Peter Lawrey Apr 27 '13 at 09:32
  • In order to transmit binary (where code points are transmitted bit for bit, with no translation or examination by the intervening code) you must transmit in a binary mode. I forget all the options here (network protocols are something I always have to look up), but I'm pretty sure one is as an attachment with a recognized binary content type. Otherwise, translate to Base64 -- this will make it through any translation and will not be interpreted as control characters. – Hot Licks Apr 27 '13 at 11:32
  • 1
    I figured it up! I used DataOutputStream with dos.write command. I have to say that this is not that comfortable as .println() :) Anyway, thanks a lot guys :) – Andrew M. Apr 27 '13 at 11:53