Легкий способ хранения/восстановления ключа шифрования для расшифровки строки в java
Для шифрования я использую что-то вроде этого:
SecretKey aesKey = KeyGenerator.getInstance("AES").generateKey();
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm());
String aesEncrypted= aesEncrypt.encrypt(StringContent);
Если я распечатаю aesKey, я получаю: "[email protected]".
Итак, для шифрования я хотел бы попросить пользователя ключ, но не знаю, как и в каком формате он должен быть.
Мой план был примерно таким:
SecretKey aesKey = [email protected];
StringEncrypter aesEncrypt = new StringEncrypter(aesKey, aesKey.getAlgorithm());
String aesDecrypt = aesEncrypt.decrypt(aesEncrypted);
Но кажется, что он не работает. Есть ли простой способ распечатать ключ после шифрования для консоли, чтобы пользователь мог его сохранить (или запомнить), а затем использовать для дешифрования?
Весь код здесь: Невозможно расшифровать cyphertext из текстового файла, симметричного ключевого инструмента. в java
Так что я сожалею о публикации снова, но я не уверен, если код даже читаем (я новичок).
Ответы
Ответ 1
Я должен был сделать это сам недавно. И хотя другие ответы здесь привели меня в правильном направлении, это могло быть проще. Итак, вот моя "доля" в течение дня, несколько вспомогательных методов для простой манипуляции с AES. (Обратите внимание на зависимость от Apache Commons и Codec.)
Теперь это все в репозитории git: github.com/stuinzuri/SimpleJavaKeyStore
import static org.apache.commons.codec.binary.Hex.*;
import static org.apache.commons.io.FileUtils.*;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import javax.crypto.*;
import org.apache.commons.codec.DecoderException;
public static SecretKey generateKey() throws NoSuchAlgorithmException
{
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256); // 128 default; 192 and 256 also possible
return keyGenerator.generateKey();
}
public static void saveKey(SecretKey key, File file) throws IOException
{
char[] hex = encodeHex(key.getEncoded());
writeStringToFile(file, String.valueOf(hex));
}
public static SecretKey loadKey(File file) throws IOException
{
String data = new String(readFileToByteArray(file));
byte[] encoded;
try {
encoded = decodeHex(data.toCharArray());
} catch (DecoderException e) {
e.printStackTrace();
return null;
}
return new SecretKeySpec(encoded, "AES");
}
Ответ 2
Большинство экземпляров Java Key
представлены в виде строки байтов в результате их метода getEncoded()
. Это то, что нужно сохранить, чтобы восстановить ключ позже.
Однако, чтобы безопасно хранить ключ в электронной форме, он должен быть зашифрован. Конечно, для шифрования ключа потребуется другой ключ (или пароль) & hellip; и поэтому у вас бесконечный регресс. Java KeyStore
может использоваться для хранения объектов SecretKey
таким образом, и это полезно, если у вас есть много секретных ключей, которые все защищены одним "главным" паролем. Но для защиты одного ключа это не имеет большого смысла.
Один из вариантов заключается в том, чтобы представить ключ пользователю в форме, которая может быть сохранена некорректно (во многих приложениях, которые могут быть на листе бумаги в их кошельке). Это может быть так же просто, как отобразить байты ключа, закодированного в шестнадцатеричном, Base-64 или другой текстовой кодировке, и попросить пользователя записать его.
Другой подход - позволить пользователю выбрать незабываемый пароль и сгенерировать ключ с помощью этого алгоритма, такого как PBKDF2. Соль (и, возможно, счетчик итераций), используемый для деривации ключей, нужно будет где-то записать. Другим недостатком является то, что люди склонны выбирать из относительно ограниченного количества паролей из общего количества доступных. Таким образом, ключи, полученные из паролей, могут быть легче угадать, чем предполагает размер ключа.
Вот иллюстрация основной техники для сохранения и восстановления секретного ключа.
byte[] encoded = aesKey.getEncoded();
/* Now store "encoded" somewhere. For example, display the key and
ask the user to write it down. */
String output = Base64.getEncoder().withoutPadding().encodeToString(encoded);
System.out.println("Keep it secret, keep it safe! " + output);
...
/* At some point, you need to reconstitute the key. Let say the user
enters it as a base-64 number that you convert to bytes. */
String input = ... ;
byte[] encoded = Base64.getDecoder().decode(input);
SecretKey aesKey = new SecretKeySpec(encoded, "AES");
Ответ 3
Я сохранил ключи в файлах java keystore. Здесь статья, которая может помочь вам
http://www.informit.com/articles/article.aspx?p=170967&seqNum=3
Ответ 4
Для справки, результат, который вы видите, является результатом метода toString
по умолчанию, а смешное число на конце - хеш-код. См. здесь. Хэш-коды по дизайну не обратимы, и toString
не обязательно гарантирует вам достаточную информацию для восстановления исходного объекта (хотя он и работает для определенных классов).