Java - шифрование/дешифрование имени пользователя и пароля из файла конфигурации

Мы занимаемся разработкой веб-сервиса Java для клиента. Возможны два варианта:

  • Храните зашифрованное имя пользователя/пароль в клиенте веб-службы. Читайте из конфига. файл на стороне клиента, расшифровать и отправить.

  • Сохраните зашифрованное имя пользователя/пароль на веб-сервере. Читайте из конфига. файл на веб-сервере, расшифровывать и использовать в веб-службе.

Имя пользователя/пароль используется веб-службой для доступа к стороннему приложению.

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

Поэтому нам нужно что-то быстрое и простое в Java.

Любые рекомендации?

Сервер Tomkat 5.5. Веб-служба - Axis2.

  • Какой шифровать/дешифровать пакет мы будем использовать?
  • Как насчет хранилища ключей?
  • Какой механизм настройки мы должны использовать?
  • Будет ли это легко развертываться?

Ответ 1

Быть в интранете, конечно, не оправдывает отказ от безопасности. Наибольший ущерб, нанесенный информации, - это инсайдеры. Посмотрите на ценность того, что защищено, и должным образом учитывайте безопасность.

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

Не распространяйте сторонний пароль за пределами веб-сервера.

Самый безопасный способ сделать это - обеспечить его веб-приложение в интерактивном режиме. Это может быть ServletContextListener, который запрашивает пароль при запуске приложения или страницу в приложении, чтобы администратор мог ввести его через форму. Пароль хранится в ServletContext и используется для аутентификации запросов сторонней службе.

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

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

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

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

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

Ответ 2

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

Тогда я бы сказал, что самым простым подходом было бы хранить пароль в зашифрованном формате (через механизм шифрования java), когда ключ шифрования/дешифрования просто закодирован в коде.

Я бы определенно сохранил его на стороне сервера (файловая система или db), а затем распространял и поддерживал его на нескольких клиентах.

Вот как это могло бы работать с шифрованием DES:

// only the first 8 Bytes of the constructor argument are used 
// as material for generating the keySpec
DESKeySpec keySpec = new DESKeySpec("YourSecr".getBytes("UTF8")); 
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
sun.misc.BASE64Encoder base64encoder = new BASE64Encoder();
sun.misc.BASE64Decoder base64decoder = new BASE64Decoder();
.........

// ENCODE plainTextPassword String
byte[] cleartext = plainTextPassword.getBytes("UTF8");      

Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread safe
cipher.init(Cipher.ENCRYPT_MODE, key);
String encrypedPwd = base64encoder.encode(cipher.doFinal(cleartext));
// now you can store it 
......

// DECODE encryptedPwd String
byte[] encrypedPwdBytes = base64decoder.decodeBuffer(encryptedPwd);

Cipher cipher = Cipher.getInstance("DES");// cipher is not thread safe
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] plainTextPwdBytes = (cipher.doFinal(encrypedPwdBytes));