Шифровать пароль в файлах конфигурации?

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

ТРЕБОВАНИЯ:

  • Шифровать пароль открытого текста, который будет храниться в файле
  • Расшифруйте зашифрованный пароль, прочитанный из файла из моей программы

Любые рекомендации о том, как я буду заниматься этим? Я думал написать собственный алгоритм, но я чувствую, что это будет ужасно неуверенно.

Простой способ сделать это – использовать шифрование на основе пароля на Java. Это позволяет шифровать и расшифровывать текст с помощью пароля.

Это в основном означает инициализацию javax.crypto.Cipher с алгоритмом "AES/CBC/PKCS5Padding" и получение ключа от javax.crypto.SecretKeyFactory с "PBKDF2WithHmacSHA512" алгоритма "PBKDF2WithHmacSHA512" .

Вот пример кода (обновленный для замены менее безопасного варианта на основе MD5):

 import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; public class ProtectedConfigFile { public static void main(String[] args) throws Exception { String password = System.getProperty("password"); if (password == null) { throw new IllegalArgumentException("Run with -Dpassword="); } // The salt (probably) can be stored along with the encrypted data byte[] salt = new String("12345678").getBytes(); // Decreasing this speeds down startup time and can be useful during testing, but it also makes it easier for brute force attackers int iterationCount = 40000; // Other values give me java.security.InvalidKeyException: Illegal key size or default parameters int keyLength = 128; SecretKeySpec key = createSecretKey(password.toCharArray(), salt, iterationCount, keyLength); String originalPassword = "secret"; System.out.println("Original password: " + originalPassword); String encryptedPassword = encrypt(originalPassword, key); System.out.println("Encrypted password: " + encryptedPassword); String decryptedPassword = decrypt(encryptedPassword, key); System.out.println("Decrypted password: " + decryptedPassword); } private static SecretKeySpec createSecretKey(char[] password, byte[] salt, int iterationCount, int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException { SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512"); PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterationCount, keyLength); SecretKey keyTmp = keyFactory.generateSecret(keySpec); return new SecretKeySpec(keyTmp.getEncoded(), "AES"); } private static String encrypt(String property, SecretKeySpec key) throws GeneralSecurityException, UnsupportedEncodingException { Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); pbeCipher.init(Cipher.ENCRYPT_MODE, key); AlgorithmParameters parameters = pbeCipher.getParameters(); IvParameterSpec ivParameterSpec = parameters.getParameterSpec(IvParameterSpec.class); byte[] cryptoText = pbeCipher.doFinal(property.getBytes("UTF-8")); byte[] iv = ivParameterSpec.getIV(); return base64Encode(iv) + ":" + base64Encode(cryptoText); } private static String base64Encode(byte[] bytes) { return Base64.getEncoder().encodeToString(bytes); } private static String decrypt(String string, SecretKeySpec key) throws GeneralSecurityException, IOException { String iv = string.split(":")[0]; String property = string.split(":")[1]; Cipher pbeCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); pbeCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(base64Decode(iv))); return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8"); } private static byte[] base64Decode(String property) throws IOException { return Base64.getDecoder().decode(property); } } 

Остается одна проблема: где вы должны хранить пароль, который вы используете для шифрования паролей? Вы можете сохранить его в исходном файле и обфускать его, но его не так уж сложно найти. В качестве альтернативы вы можете -DpropertyProtectionPassword=... его как системное свойство при запуске Java-процесса ( -DpropertyProtectionPassword=... ).

Эта же проблема сохраняется, если вы используете KeyStore, который также защищен паролем. В принципе, вам понадобится один мастер-пароль, и его довольно сложно защитить.

Да, определенно не пишите свой собственный алгоритм. Java имеет множество криптографических API.

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

Проверьте jasypt , которая представляет собой библиотеку, предлагающую базовые возможности шифрования с минимальными усилиями.

Я считаю, что лучший подход – обеспечить, чтобы ваш файл конфигурации (содержащий ваш пароль) был доступен только для определенной учетной записи пользователя . Например, у вас может быть пользовательский пользовательский appuser для которого только доверенные люди имеют пароль (и к которому они su ).

Таким образом, нет назойливой криптографии, и у вас все еще есть безопасный пароль.

EDIT: Я предполагаю, что вы не экспортируете конфигурацию своего приложения за пределы надежной среды (что я не уверен, что это будет иметь смысл, учитывая вопрос)

Ну, чтобы решить проблемы мастер-пароля – лучший подход – не хранить пароль нигде, приложение должно шифровать пароли для себя – чтобы только он мог их расшифровать. Поэтому, если бы я использовал файл .config, я бы сделал следующее: mySettings.config :

encryptTheseKeys = SecretKey, anotherSecret

SecretKey = unprotectedPasswordThatIputHere

anotherSecret = anotherPass

someKey = unprotectedSettingIdontCareAbout

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

encryptTheseKeys = SecretKey, anotherSecret

secretKey = crypt: ii4jfj304fjhfj934fouh938

anotherSecret = crypt: jd48jofh48h

someKey = unprotectedSettingIdontCareAbout

Просто убедитесь, что вы сохранили оригиналы в своем безопасном месте …

Большая точка, и слон в комнате, и все такое, заключается в том, что если ваше приложение может получить пароль, тогда хакер, имеющий доступ к коробке, сможет его удержать!

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

Однако даже при таком уровне раздражения, если хакеру удается получить root-доступ (или даже просто получить доступ как пользователь, запускающий ваше приложение), он может сбросить память и найти там пароль.

Дело в том, чтобы не допустить, чтобы вся компания имела доступ к серверу производства (и тем самым к паролям) и следила за тем, чтобы эту коробку не удалось взломать!

Попробуйте использовать методы шифрования ESAPI. Его легко настроить, и вы также можете легко изменить свои ключи.

http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/org/owasp/esapi/Encryptor.html

Вы

1) шифровать 2) расшифровывать 3) знак 4) unsign 5) хешировать 6) сигнатуры, основанные на времени, и многое другое только с одной библиотекой.

Посмотрите, что доступно в Jetty для хранения пароля (или hashей) в файлах конфигурации, и подумайте, может ли быть использована OBF-кодировка для вас. Затем посмотрите в источнике, как это делается.

http://www.eclipse.org/jetty/documentation/current/configuring-security-secure-passwords.html

В зависимости от того, насколько безопасны вам файлы конфигурации или насколько надежны ваше приложение, http://activemq.apache.org/encrypted-passwords.html может быть хорошим решением для вас.

Если вы не слишком боитесь, что пароль дешифруется, и его можно очень просто настроить с помощью компонента для хранения ключа пароля. Однако, если вам нужна дополнительная безопасность, вы можете установить переменную окружения в секретный раздел и удалить ее после запуска. При этом вам нужно беспокоиться о том, что приложение / сервер идет вниз, а не приложение, которое автоматически не перезапускается.

Если вы используете java 8, использование внутреннего кодера и декодера Base64 можно избежать, заменив

return new BASE64Encoder().encode(bytes);

с

return Base64.getEncoder().encodeToString(bytes);

а также

return new BASE64Decoder().decodeBuffer(property);

с

return Base64.getDecoder().decode(property);

Обратите внимание, что это решение не защищает ваши данные, поскольку методы дешифрования хранятся в одном месте. Это просто усложняет разрыв. В основном это позволяет избежать печати и показать его всем по ошибке.

  • Почему при использовании функции Non-Random IV с режимом CBC существует уязвимость?
  • Шифрование шифрования RSA в iphone
  • Как сохранить / получить открытый / закрытый ключ RSA
  • Учитывая, что последний блок не заполнен неправильно
  • Использование SHA1 и RSA с java.security.Signature против MessageDigest и Cipher
  • C # Экспорт частного / открытого ключа RSA из RSACryptoServiceProvider в строку PEM
  • Подтвердить подпись Authenticode на EXE-C ++ без CAPICOM
  • Android 4.2 нарушил мой шифрованный / дешифрованный код, и предоставленные решения не работают
  • Может ли две разные строки генерировать один и тот же MD5-hash-код?
  • Поведение Crypto / AES по умолчанию Java по умолчанию
  • Какой тип данных использовать для hashированного поля пароля и какой длины?
  • Interesting Posts

    Застрял в командной строке GRUB после регулярного обновления ядра

    Зеркальные ячейки, чтобы изменения в любой ячейке обновляли другую

    Что такое дифференциальное исполнение?

    Делает много в конструкторах плохо?

    Совместное использование буфера обмена Virtualbox

    Visual Studio: существует ли рефакторинг «переместить class в другое пространство имен»?

    Excel, как найти номер столбца min значение?

    Какие специальные переменные доступны при написании команды оболочки для контекстного меню

    Восстановить данные на жестком диске?

    Мой контрольный ключ не работает, как его исправить?

    Могу ли я получить список подключенных клиентов на openvpn (например, «список hamachi»?)

    Единичное тестирование недействительных методов?

    Являются ли закодированные логические операторы короткими законами? И порядок оценки?

    Как создавать и развертывать образы Linux

    Почему конструктор копирования принимает свой параметр по ссылке в C ++?

    Давайте будем гением компьютера.