Хешированные пароли, обновленные через JDBC, становятся поврежденными. (Больше проблем с кодированием, чем с хешированием) - PullRequest
1 голос
/ 07 октября 2010

Я пробовал следующее с MySQL UTF-8 и Latin-1, но безрезультатно.

Я хэширую свои пароли (в данном случае для защиты), используя SHA-1, примерно так:

  if(toSecurify == null) {
   throw new Exception("toSecurifyString must not be null");
  }
  try {
   MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
   byte[] sha1HashBytes = new byte[40];
   messageDigest.update(toSecurify.getBytes(), 0, toSecurify.length());
   sha1HashBytes = messageDigest.digest();
   return new String(sha1HashBytes, "UTF-8");
  } catch(NoSuchAlgorithmException nsae) {
   throw new Exception("Hash algorithm not supported.");
  } catch(UnsupportedEncodingException uee) {
   throw new Exception("Encoding not supported.");
  }

Затем я сохраняю это в столбце пароля базы данных mysql.

Теперь вот сложная часть, которую я могу запросить в db вроде: Есть ли запись с

username=<insertUserName> and password = thatHashFunctionUpThere(<insertPassword>);

Это прекрасно работает.

Но теперь обновление записей выглядит примерно так:

String userName = someJdbcStuffToGetUsername();
String password = someJdbcStuffToGetPassword();

update(userName, password);

Пароль теперь изменился! Это портит пароли. Это как при выходе (при запросе) он искажается, но никогда не входит. Я говорю это потому, что вставки и запросы работают отлично, но когда я получаю значение, а затем устанавливаю его снова, оно повреждает его, поэтому оно должно быть на выходе.

У кого-нибудь есть мысли? Где на выходе я должен искать проблемы с кодировкой?

Заранее спасибо, ребята!

1 Ответ

2 голосов
/ 10 октября 2010

В вашем коде есть изъян.

return new String(sha1HashBytes, "UTF-8"); 

Вы не должны трактовать байты как символы.Фактически вы должны преобразовать каждый байт в 2-символьную шестнадцатеричную строку.Например,

StringBuilder hex = new StringBuilder(sha1HashBytes.length * 2);
for (byte b : sha1HashBytes) {
    if ((b & 0xff) < 0x10) hex.append("0");
    hex.append(Integer.toHexString(b & 0xff));
}
return hex.toString();

Но лучше просто использовать собственную функцию MySQL SHA1()INSERT do:

String sql = "INSERT INTO user (username, password) VALUES (?, SHA1(?))";
// ...
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(username);
preparedStatement.setString(password); // This one should be unhashed!!
int affectedRows = preparedStatement.executeUpdate();
// ...

и в UPDATE:

String sql = "UPDATE user SET username = ?, password = SHA1(?) WHERE id = ?";
// ...
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(username);
preparedStatement.setString(password); // This one should be unhashed!!
preparedStatement.setLong(id);
int affectedRows = preparedStatement.executeUpdate();
// ...

и SELECT:

String sql = "SELECT * FROM user WHERE username = ? AND password = SHA1(?)";
// ...
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(username);
preparedStatement.setString(password); // This one should be unhashed!!
resultSet = preparedStatement.executeQuery();
// ...

См. Также:

...