4

I need to convert a salt value randomly generated and store it in the database. To store it in the database I converted it to a string. Then for retrieving the original value, I convert it back to byte. But both value are not matching. I have tried "UTF-8","UTF-16", BASE64Encoder.

SecureRandom ranGen = new SecureRandom();
byte[] aesKey = new byte[16]; // 16 bytes = 128 bits
ranGen.nextBytes(aesKey);   
System.out.println(aesKey);

String a=new String(aesKey,"UTF-16");
byte[] b=new byte[16];
b=a.getBytes("UTF-16");
System.out.println(b);

Outputs for the above code(Executed it 2 times):

[B@11563ff
[B@1581593

and

[B@170888e
[B@11563ff
Ashwin
  • 12,691
  • 31
  • 118
  • 190
  • What is the output of the two System outs? – DaveJohnston Feb 15 '12 at 09:16
  • 1
    As I said in my answer, what you are printing out here is the Object toString output, which by default is getClass().getName() + "@" + Integer.toHexString(hashCode()). So since you have two different byte arrays (i.e. not the same Object) the output is different. – DaveJohnston Feb 15 '12 at 09:37
  • As DaveJohnston implies, you should be careful when using toString() in the java language. – Sirs Feb 15 '12 at 09:46

2 Answers2

5

You really ought to use Base64 for converting binary data to Strings. There are lots of free implementations available, for example the one found in Apache Commons Codec.

Also, it's really easy to use, for example:

For encoding:

import org.apache.commons.codec.binary.Base64;
...
byte[] abValue = {...}; // Your data to encode
Base64 base64 = new Base64();
String strEncodedData = base64.encodeToString(abValue).trim();

For decoding:

import org.apache.commons.codec.binary.Base64;
...
String strEncodedData = "..."; // Your previously encoded data
Base64 base64 = new Base64();
byte[] abValue = base64.decode(strValue);
Sirs
  • 1,277
  • 17
  • 30
4

As your code is written above, printing aesKey and then b, what you are actually printing is the output of the toString method for an array object, which is just the default Object toString method. So I don't see how you can expect them to be the same.

If you really want to check they are the same you should compare them byte by byte.

In terms of your actual question regarding storing a byte[] as a String in the DB, your best bet is to Base64 encode it. I would suggest using the Apache Commons Codec library for this. See the user guide.

EDIT:

Using the BASE64Encode and BASE64Decoder you have referred to, the code would be like this:

    SecureRandom ranGen = new SecureRandom();
    byte[] aesKey = new byte[16]; // 16 bytes = 128 bits
    ranGen.nextBytes(aesKey);
    String a = new BASE64Encoder().encode(aesKey);

    System.out.println(a);

    byte[] b = new BASE64Decoder().decodeBuffer(a);
    System.out.println(new BASE64Encoder().encode(b));

    for (int i = 0; i < aesKey.length; i++) {
        System.out.println(aesKey[i] + " " + b[i]);
    }

Here, I have also looped through the bytes individually, to show that they are indeed equal.

DaveJohnston
  • 10,031
  • 10
  • 54
  • 83
  • Correct me if I am wrong. If the two bytes are equal in every sense. Then their even the default object toString should give the same value. – Ashwin Feb 15 '12 at 09:29
  • They are byte arrays, and they are not the same object, so the default toString method will not return the same result. – DaveJohnston Feb 15 '12 at 09:32
  • So is it returning their object address, – Ashwin Feb 15 '12 at 09:34
  • It is writing: getClass().getName() + "@" + Integer.toHexString(hashCode()) – DaveJohnston Feb 15 '12 at 09:38
  • The hashCode method in Object is native, and as far as I know is not exactly the address of the Object in memory, but something related to that. – DaveJohnston Feb 15 '12 at 09:41
  • There are other questions about that topic, e.g. :http://stackoverflow.com/questions/557574/what-is-native-implementation-in-java/565416#565416 – DaveJohnston Feb 15 '12 at 09:42
  • Thank you. The discussion was very useful. – Ashwin Feb 15 '12 at 09:50
  • Keep in mind it is not recommended to use sun.* classes like Base64Encoder, since they are not supported by Sun and may disappear from future versions of the Java virtual machine. – Sirs Feb 15 '12 at 10:19
  • @Sirs agreed on that point, and I did suggest using the Apache Commons Codec library, which I use extensively in my projects at work. – DaveJohnston Feb 15 '12 at 11:23
  • I guessed you knew that :-), I suspect the Original Poster might not, that's why I pointed it out. – Sirs Feb 15 '12 at 11:37