Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AES Key encoded byte[] to String and back to byte[]

In the similar question "Conversion of byte[] into a String and then back to a byte[]" is said to not to do the byte[] to String and back conversion, what looks like apply to most cases, mainly when you don't know the encoding used.

But, in my case I'm trying to save to a DB the javax.crypto.SecretKey data, and recoverd it after.

The interface provide a method getEncoded() which returns the key data encoded as byte[], and with another class I can use this byte[] to recover the key.

So, the question is, how do I write the key bytes as String, and later get back the byte[] to regenerate the key?

like image 362
The Student Avatar asked Dec 28 '22 15:12

The Student


2 Answers

javax.crypto.SecretKey is binary data, so you can't convert it directly to a String. You can encode it as a hex string or in Base64.

See Apache Commons Codec.

Update: If you dont want to depend on third-party libraries (and can't/don't want to store plain binary data, as Jon suggests) you can do some ad-hoc encoding, for example, following erickson's suggestion:

public static String bytesToString(byte[] b) {
    byte[] b2 = new byte[b.length + 1];
    b2[0] = 1;
    System.arraycopy(b, 0, b2, 1, b.length);
    return new BigInteger(b2).toString(36);
}

public static byte[] stringToBytes(String s) {
    byte[] b2 = new BigInteger(s, 36).toByteArray();
    return Arrays.copyOfRange(b2, 1, b2.length);
}

It's rather, ugly, non-standard and not optimal (in output size). But it's also very small, correct and it has no dependencies; it can be practical, specially if your data is small sized.

Updated: I replaced the Character.MAX_RADIX by the literal value (36), following GregS's comment. It might seem less elegant but it's actually more secure. (You can also use 32 or 16).

like image 129
leonbloy Avatar answered Jan 07 '23 11:01

leonbloy


Use a base-64 encoding to safely convert arbitrary binary data to a string and back.

The Apache Commons Codec library provides code for this, as do various others. (I'm not terribly keen on the API to Apache Commons Codec, admittedly. I don't know of any other libraries with this functionality off hand but I'm sure they exist.)

EDIT: This project provides a single file for fast encoding and decoding, and has sane method signatures - as well as plenty of extra options should you need them.

Alternatively, if the point is to save it to a database, why not just use an appropriate binary data field (Image/Blob or whatever applies to your database) rather than storing it as a string in the first place?

like image 39
Jon Skeet Avatar answered Jan 07 '23 10:01

Jon Skeet