Как получить действительный секретный ключ из хранилища ключей в java? - PullRequest
0 голосов
/ 11 февраля 2020

Я не очень осведомлен о Java KeyStore. Я хочу иметь зашифрованную структуру для хранения моих ключей.

У меня несколько кластеров, и существует ключ, связанный с каждым кластером, и теперь я хочу надежно хранить эти ключи, чтобы они все были зашифрованы с использованием одного главного ключа (например, loginid)

Я много бродил в поисках этой проблемы и где-то на самом стеке overflow кто-то предложил около Java keyStore для хранения SecretKey (Symmetri c Encryption). Я прочитал его документацию и нашел ее идеальной в соответствии с моими требованиями, но не смог правильно понять ее реализацию.

Вот фрагмент кода, над которым я работаю -


public class Prac {

    public static void main(String[] args) throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, UnrecoverableEntryException {
        KeyStore ks = KeyStore.getInstance("JCEKS");        
        char[] ksPwd = "yashkaranje98".toCharArray();        
        ks.load(null, ksPwd);        
        KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(ksPwd);

        javax.crypto.SecretKey mySecretKey = new SecretKeySpec("_anky!@ubn#$0e41".getBytes(),"AES");
        KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey);
        ks.setEntry("cluster1", skEntry, protParam);

        java.io.FileOutputStream fos = null;
        try {
            fos = new java.io.FileOutputStream("keystore.ks");
            ks.store(fos, ksPwd);
        } finally {
            if (fos != null) {
                fos.close();
            }
        }

        java.io.FileInputStream fis = null;
        try {
          ks.load(new FileInputStream("keystore.ks"), ksPwd);
        } finally {
                if (fis != null) {
                        fis.close();
                }
        }


        SecretKey key = (SecretKey)ks.getKey("cluster1", ksPwd);
        String encodedKey = Base64.getEncoder().encodeToString(key.getEncoded());
        System.out.println(encodedKey);  

    }
}

Псевдоним: "cluster1"

Ключ для хранения: _anky! @ Ubn # $ 0e41

Параметр защиты: yashkaranje98

Печатается: X2Fua3khQHVibiMkMGU0MQ ==

То, что я ожидаю, это главное: _anky! @ Ubn # $ 0e41

Пожалуйста, дайте мне знать, что мне не хватает ... но прежде, пожалуйста, скажите мне, что я Я ожидаю, что это даже le git? или это имеет смысл?

(я все еще изучаю эту концепцию KeyStore, поэтому могут быть некоторые глупые ошибки.)

1 Ответ

1 голос
/ 13 февраля 2020

Секретный ключ AES состоит из случайных байтов. Такой ключ должен быть напечатан , а не напрямую, потому что байты могут не представлять допустимые символы или они могут представлять управляющие символы, которые не печатаются на экране. Если вы скопируете их, вы можете пропустить данные. Если вы печатаете их не в том терминале, вы можете отправить управляющие коды терминала.

Из-за этого вам нужно , чтобы распечатать значения ключей в виде шестнадцатеричных или базовых 64. Обычно для симметричных ключей c Предпочтителен шестнадцатеричный формат, поскольку легко увидеть содержимое и размер из шестнадцатеричного числа (размер в байтах вдвое меньше размера шестнадцатеричного числа, размер в битах в 4 раза больше размера шестнадцатеричного числа, чем каждый шестнадцатеричный ди git представляет 4-битный клев). Однако, поскольку Java по-прежнему не хватает хорошего шестнадцатеричного кодера, base 64 также является хорошим вариантом.

Конечно, в этом случае, для сравнения, вы также должны декодировать его из base 64, прежде чем вставить его в хранилище ключей.


Также учтите, что вы не указываете кодировку символов при вызове getBytes в строке. Если вы будете использовать более ценные символы, вы можете получить разные результаты в разных системах, так как getBytes без аргументов предполагает кодировку платформы. Указание StandardCharsets.UTF_8 обычно имеет больше смысла.

Конечно, поскольку ключи должны содержать случайные байты, метод getBytes должен полностью go, но вы все равно должны помнить об этом.


Когда я смотрю на код, кажется, что вы пропустили последние 10 лет Java прогресса. Нет var, нет null избегания, отсутствует импорт и нет попытки с ресурсами. Это позор, потому что это сделает ваш код более читабельным. Это верно, заметьте, но да ...

...