在类似的问题"Conversion of byte[] into a String and then back to a byte[]"被认为不执行字节[]到字符串和反向转换,看起来适用于大多数情况,主要是当你不知道使用的编码时。
但是,在我的情况下,我正在尝试将数据库中的javax.crypto.SecretKey数据保存到数据库中,然后将其恢复。
接口提供了一个方法getEncoded(),它返回编码为byte []的密钥数据,而另一个类我可以使用这个byte []来恢复密钥。
所以,问题是,如何将关键字节写为String,然后返回byte []以重新生成密钥?
答案 0 :(得分:6)
javax.crypto.SecretKey
是二进制数据,因此您无法将其直接转换为String。您可以将其编码为十六进制字符串或Base64。
更新:如果您不想依赖第三方库(并且不能/不想存储纯二进制数据,正如Jon建议的那样),您可以做一些特别的编码,例如,遵循埃里克森的建议:
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);
}
相当,丑陋,非标准且不是最佳(输出尺寸)。但它也非常小,正确且没有依赖性;它可以是实用的,特别是如果你的数据很小的话。
更新:我按照GregS的评论将Character.MAX_RADIX
替换为文字值(36)。它可能看起来不那么优雅,但它实际上更安全。 (您也可以使用32或16)。
答案 1 :(得分:3)
使用base-64编码将任意二进制数据安全地转换为字符串并返回。
Apache Commons Codec库为此提供代码,其他各种代码也是如此。 (诚然,我对Apache Commons Codec的API并不十分热衷。我不知道任何其他具有此功能的库 off hand 但我确信它们存在。)
编辑:This project提供了一个用于快速编码和解码的文件,并且具有合理的方法签名 - 以及您需要的大量额外选项。
或者,如果要将其保存到数据库,为什么不使用适当的二进制数据字段(Image / Blob或适用于您的数据库的任何内容)而不是首先将其存储为字符串?
答案 2 :(得分:1)
如何编码为数字而不是字符串?它不像Base-64那么紧凑,但你可以省略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);
答案 3 :(得分:0)
你不能使用String构造函数:String(byte [] data,String charsetName),如:
byte[] data=new byte[1024];
String key=new String(data,"UTF-8");
以后你可以这样做:
String key="mymostsecretaeskey";
byte[] data=key.getBytes("UTF-8");