Ключ AES, закодированный байтом [] в строку и обратно в байт [] - PullRequest
4 голосов
/ 26 мая 2010

В аналогичном вопросе "Преобразование байта [] в строку и затем обратно в байт []" , как говорят, не выполняет преобразование байта [] в строку и обратно, что выглядит как применяется в большинстве случаев, в основном, когда вы не знаете, какую кодировку используете.

Но в моем случае я пытаюсь сохранить в БД данные javax.crypto.SecretKey и восстановить их после.

Интерфейс предоставляет метод getEncoded (), который возвращает данные ключа, закодированные как byte [], и с другим классом я могу использовать этот байт [] для восстановления ключа.

Итак, вопрос в том, как записать байты ключа как String, а затем получить обратно байт [] для регенерации ключа?

Ответы [ 4 ]

6 голосов
/ 26 мая 2010

javax.crypto.SecretKey - это двоичные данные, поэтому вы не можете преобразовать их напрямую в строку. Вы можете закодировать его в виде шестнадцатеричной строки или в Base64.

См. Кодек Apache Commons .

Обновление : если вы не хотите зависеть от сторонних библиотек (и не можете / не хотите хранить простые двоичные данные, как предлагает Джон), вы можете выполнить специальное кодирование Например, следуя предложению Эриксона:

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);
}

Это довольно, некрасиво, нестандартно и не оптимально (по размеру вывода). Но он также очень маленький, правильный и не имеет никаких зависимостей; это может быть практичным, особенно если ваши данные небольшого размера.

Обновлено: я заменил Character.MAX_RADIX на буквальное значение (36), следуя комментарию GregS. Это может показаться менее элегантным, но на самом деле это более безопасно. (Вы также можете использовать 32 или 16).

3 голосов
/ 26 мая 2010

Используйте кодировку base-64 для безопасного преобразования произвольных двоичных данных в строку и обратно.

Библиотека Apache Commons предоставляет код для этого, как и другие. (Я не очень люблю API для Apache Commons Codec, по общему признанию. Я не знаю других библиотек с этой функциональностью от руки , но я уверен, что они существуют.)

РЕДАКТИРОВАТЬ: Этот проект предоставляет один файл для быстрого кодирования и декодирования и имеет подписи вменяемого метода - а также множество дополнительных опций, если они вам понадобятся.

В качестве альтернативы, если цель заключается в том, чтобы сохранить его в базе данных, почему бы просто не использовать соответствующее поле двоичных данных (изображение / блоб или все, что применимо к вашей базе данных), а не сохранять его как строку в первую очередь?

1 голос
/ 26 мая 2010

Как насчет кодирования в виде числа вместо строки символов? Он не так компактен, как 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);
0 голосов
/ 26 мая 2010

Не можете использовать конструктор 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");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...