2

I'm working on a cross-platform encryption system. One of the requirements is to easily encrypt and decrypt strings in out application code.

The encryption class works flawlessly, but I'm having trouble with string encoding on the java side.

Currently, I have the following static methods:

public static String encrypt(String key, String data)
{
    byte[] decoded_key;
    byte[] decoded_data;
    try
    {
        decoded_key = key.getBytes("UTF-8");
        decoded_data = data.getBytes("UTF-8");
    }
    catch (Exception e)
    {
        //Not Supposed to happen.
        throw new RuntimeException();
    }

    if(decoded_key.length != 16) 
        throw new IllegalArgumentException("Key length must be of 16 bytes. Given is " + decoded_key.length + ".");

    try
    {
        return(IOUtils.toString(encrypt(decoded_key, decoded_data), "UTF-8"));
    }
    catch (Exception e)
    {
        //Not Supposed to happen.
        throw new RuntimeException();
    }
}

public static String decrypt(String key, String data)
{
    byte[] decoded_key;
    byte[] decoded_data;
    try
    {
        decoded_key = key.getBytes("UTF-8");
        decoded_data = data.getBytes("UTF-8");
    }
    catch (Exception e)
    {
        //Not Supposed to happen.
        throw new RuntimeException();
    }

    if(decoded_key.length != 16) 
        throw new IllegalArgumentException("Key length must be of 16 bytes. Given is " + decoded_key.length + ".");

    try
    {
        return(IOUtils.toString(decrypt(decoded_key, decoded_data), "UTF-8"));
    }
    catch (Exception e)
    {
        //Not Supposed to happen.
        throw new RuntimeException();
    }
}

My unit tests are failing when decrypting. I ran a test where I compared a byte array of encoded UTF-8 data encoded_data with IOUtils.toString(encoded_data, "UTF-8").getBytes("UTF-8") and for some reason they turned out to be different arrays altogether. No wonder my decryption algorithm is failing.

What is the proper procedure to convert from a java string to a UTF-8 byte array and back to a java string?

15
  • why are you representing your "keys" as Strings in the first place? presumably they are arbitrary bytes? you are probably corrupting your keys by converting them into Strings in the first place. Commented May 16, 2013 at 15:38
  • business requirement. My encryption class uses bytes. Commented May 16, 2013 at 15:45
  • you're missing my point. how are you maintaining the keys as strings without corrupting them? Commented May 16, 2013 at 15:49
  • @jtahlborn maybe the key is alphanumeric? I would see a problem if he tries to convert the encrypted raw bytes to a string. Commented May 16, 2013 at 15:49
  • @jtahlborn If I was maintaining string integrity I wouldn't be asking this question in the first place. It's not the keys giving me trouble here. Alex is correct, the string is always going to be alphanumeric. Commented May 16, 2013 at 15:53

2 Answers 2

4

the problem is that you are converting your encrypted data to a String. encrypted data is binary, not String data. UTF-8 is a charset with a specific encoding format. arbitrary binary data is not valid UTF-8 data. when you convert the encrypted data into a String, the "invalid" characters are most likely getting replaced with the ? invalid char.

If you want to convert arbitrary binary data (aka encrypted data) into a String, you need to use some binary->text conversion like Base64.

Sign up to request clarification or add additional context in comments.

1 Comment

I added an example to your answer. Thanks for the help.
0

I would try out checking first that the output of your encrypt method matches the one you are expecting with a unit test.

Also it's a good idea to use Base64 after the encryption so you can convert it to a string.

Another common issue is converting int to bytes as if they were unsigned ints. Bytes range is -128 to 127.

8 Comments

the methods aren't recursive, they take Strings, they call methods taking byte[]s.
Oops you are right that's a strange use of polymorphism over there. I imagine that there are some duplicate code/checks on the other method.
It's not strange at all, they are both decrypt, but for different types of parameters. The string version prepares everything for the byte array method.
@elite5472 if(decoded_key.length != 16) should be checked on your byte accepting method. And I'm pretty sure you are already doing it in there as well.
@Alex this isn't production code. I'm still working on it. I needed to check if string encoding is working correctly before anything else.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.