1

I have problems with sending AES encrypted data from JAVA to PHP.

My encrypt function:

public static byte[] encrypt(String input, String key, String iv) {

    byte[] raw = key.getBytes(Charset.forName("UTF8"));
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    try {
        Cipher cipher = Cipher.getInstance(CIPHER_MODE);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv.getBytes()));
        return cipher.doFinal(padString(input).getBytes("UTF-8"));
    } catch (Exception e) {
    }

    return new byte[0];
}

encrypt function is returning data in byte array To send POST data, I'm using apache HttpClient/HttpPost (preferred, but not necessary)

    HttpEntity params = MultipartEntityBuilder.create()
            .addTextBody("data1", new String(encodedData1, Charset.forName("UTF8")))
            .addTextBody("data2", new String((encodedData2, Charset.forName("UTF8")))
            .addTextBody("data3", "data3").build();

Now, I recieve data with PHP server (i can't add functionality here)

        $data1 = filter_input(INPUT_POST, 'data1');
        $data2 = filter_input(INPUT_POST, 'data2');
        $data1decoded = DecryptAES($data1, $key, $iv);
        $data2decoded = DecryptAES($data2, $key, $iv);

What is a proper way to send encoded byte[] from JAVA to PHP? I know, that Base64.encode would be probably best option, but unfortunately (as I have mentioned earlier) I can't modify PHP server-side code... new String(encodedData1, Charset.forName("UTF8")) is not working.

In node.js I can use toString('binary') to send data in proper format.

PsychoX
  • 1,050
  • 4
  • 20
  • 42
  • Do mix text with binary or you will get corruption. Also it is not clear to me what language you are using. Can you post what you have tried? – Peter Lawrey May 22 '14 at 12:07
  • Java. I need to rewrite old library to Java... And client receiving data is written in PHP. – PsychoX May 22 '14 at 12:09
  • I don't see why you would need to convert at all, please post relevant PHP code, otherwise this question cannot be answered (at least not by me, and I presume by anybody else that lacks a crystal ball). – Maarten Bodewes May 23 '14 at 09:07
  • I have updated my original question – PsychoX May 23 '14 at 09:14
  • @owlstead Is there a way to send binary data to php in one array with normal string? – PsychoX May 23 '14 at 10:45
  • 1
    Normally base 64 encoding is used for that. – Maarten Bodewes May 23 '14 at 14:09
  • HTTP POST allows for binary data, MIME as well, so you could try and use [this method](http://hc.apache.org/httpcomponents-client-4.3.x/httpmime/apidocs/org/apache/http/entity/mime/MultipartEntityBuilder.html#addBinaryBody(java.lang.String,%20byte[])) to add binary content. So don't convert all the way back to `HttpEntity`. – Maarten Bodewes May 23 '14 at 14:15
  • 1
    @owlstead I've tried with MultipartEntityBuilder#addBinaryBody, but it's content goes to PHP $_FILES array. Am I missing something? – PsychoX May 23 '14 at 14:25
  • I'm not sure what you are missing, obviously I'm missing what is performed in `DecryptAES`. – Maarten Bodewes May 25 '14 at 13:33
  • @owlstead DecryptAES is Crypt_AES() from http://phpseclib.sourceforge.net – PsychoX May 27 '14 at 09:33
  • https://github.com/phpseclib/phpseclib/blob/master/phpseclib/Crypt/AES.php – PsychoX May 27 '14 at 09:55
  • Have you tried just converting any bytes to a string directly? http://stackoverflow.com/questions/8512121/byte-to-string-java - the question here has a simple way of doing it, that's different than what you're trying. – dAngelov May 29 '14 at 18:34
  • Why are you returning return new byte[0];? shouldn't it be return raw ? – Hirak May 30 '14 at 05:59
  • @dAngelov Yes. I have tried few ways of converting byte[] to String. Unfortunately they are not good for PHP. – PsychoX May 30 '14 at 06:45

3 Answers3

1

You can't just create new String (Java is too fancy for that).

Use

public static String byteToString(byte[] bytes) {
    StringBuilder b = new StringBuilder();
    for (byte c : bytes) {
        b.append((char) (c >= 0 ? c : 256 + c));
    }
    return b.toString();
}

Using your example

HttpEntity params = MultipartEntityBuilder.create()
          .addTextBody("data", byteToString(data))
          .build();
mleko
  • 9,108
  • 5
  • 41
  • 68
0

Instead of

new String(encodedData1, Charset.forName("UTF8"))

you should use

new String(encodedData1)
0

Your byte array doesn't contain an UTF8 text anymore once it has been encrypted. You would preserve the exact structure of your byte aray by sending it in its original form with the addBinaryBody method instead of casting it to a String in order to use the addTextBody method.

user327961
  • 2,188
  • 3
  • 18
  • 19