开发者

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 d开发者_如何学Con'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?


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).


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?


How about encoding as a number instead of a character string? It's not quite as compact as Base-64, but you can leave out Apache Commons.

/* Store the key. */
BigInteger n = new BigInteger(1, key.getEncoded()); /* Store as NUMBER, or … */
String s = n.toString(32);                          /* … store as VARCHAR. */

/* Reconstruct the key (may need to pad most significant bytes with zero). */
BigInteger n = new BigInteger(s); /* Load from VARCHAR, or … */
byte[] raw = n.toByte();          /* … load from NUMBER. */
byte[] original = new byte[16];
System.arraycopy(raw, 0, original, 16 - raw.length, raw.length);


Couldn't you use the String constructor: String(byte[] data,String charsetName) as in:

byte[] data=new byte[1024];
String key=new String(data,"UTF-8");

and later you can do:

String key="mymostsecretaeskey";
byte[] data=key.getBytes("UTF-8");
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜