Безопасное хранение пароля в Java программе

Пишу простую программу на Java, которая периодически подключается к серверу. При отправке каждого запроса на сервер мне нужно передать и логин и пароль. Программа работает на моем компьютере на OS Windows. Как безопасно хранить пароли и в то же время каждый раз не вводить их?


Ответы (2 шт):

Автор решения: lampa

Сохранить логин/пароль в файл для хранения, предварительно запаролив и при каждом запуске программы вводить ключ, например так:

package com.lampa.keys;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.util.Arrays;

public class Main {
    // функция для шифровки и дешифровки сообщения
    public static byte[] crypt(int mode, byte[] value, String secret) throws Exception {
        byte[] key = secret.getBytes(StandardCharsets.UTF_8);
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16);
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(mode, secretKey);

        return cipher.doFinal(value);
    }

    public static void main(String[] args) {
        // файл, где будем хранить логин и пароль
        File passwordFile = new File("passwords.key");
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        String login = "";
        String password = "";

        // если файл существует, то пытаемся его прочитать с помощью ключа
        if(passwordFile.exists()) {
            try {
                byte[] encrypted = Files.readAllBytes(passwordFile.toPath());
                System.out.println("Write key");
                String key = reader.readLine();

                String[] result = new String(crypt(Cipher.DECRYPT_MODE, encrypted, key), StandardCharsets.UTF_8).split(":");
                login = result[0];
                password = result[1];
            }
            catch (Exception ex) {
                System.err.printf("error read password from file %s", ex.getMessage());
            }
        }
        // если файл не существует, то создаем его и шифруем ключом 
        else {
            try {
                System.out.println("Write login");
                login = reader.readLine();
                System.out.println("Write password");
                password = reader.readLine();
                System.out.println("Write key");
                String key = reader.readLine();

                FileOutputStream outputStream = new FileOutputStream(passwordFile);
                outputStream.write(crypt(Cipher.ENCRYPT_MODE, (login + ":" + password).getBytes(StandardCharsets.UTF_8), key));
                outputStream.close();
            }
            catch (Exception ex) {
                System.err.printf("error write password to file %s", ex.getMessage());
            }
        }

        System.out.printf("login: %s, password: %s%n", login, password);
    }
}
→ Ссылка
Автор решения: palshyn

В результате выбрал хранение пароля в windows credential manager. Вот проект на основе библиотеки java jna: https://github.com/dariusz-szczepaniak/java.jna.WindowsCredentialManager

→ Ссылка