Можете ли вы получить этот же Java SHA-1 в PHP, пожалуйста? - PullRequest
4 голосов
/ 22 января 2011

Я чувствую необходимость изменить платформы веб-сайтов с Java на PHP, но я хотел бы сохранить все пароли своих пользователей ...

У меня был этот код для хеширования пароля перед записью хешированного значения в качестве пароля на сайт:

MessageDigest md = null;
md = MessageDigest.getInstance("SHA");
md.update(plaintext.getBytes("UTF-8"));
byte raw[] = md.digest();
hash = new Base64().encodeToString(raw).replaceAll("\n", "").replaceAll("\r", "");

Я думаю, что код Java выполнял хеширование пароля SHA-1, но перед этим он был закодирован в байт в UTF-8, а затем в кодировке Base64.

Я бы хотел, чтобы код PHP делал то же самое, то есть возвращал то же значение хэша для того же пароля, что и в Java, только кажется, что код PHP, выполняющий хэширование SHA-1, у меня не вернется то же самое значение SHA (-1, не закодированное Base64, я думаю?) по сравнению с декодированным значением Java Base64 хеша ... может ли это быть связано с тем фактом, что мои пароли в PHP не являются байтами UTF-8 сначала закодировать (и как я могу это сделать в PHP), пожалуйста?

приписка

Еще одна странная вещь ... все мои пароли в Java имеют длину 28 символов (обычно что-то вроде этого rnwn4zTNgH30l4pP8V05lRVGmF4=) ... но значение Base64().decode(hash) этих хэшей паролей составляет 10 символов (пример [B@14e1f2b) .

Я думал, что Base64 сделал дополнительный 1 символ для каждых 3 символов (28 или 27, исключая padding = charter, намного больше, чем на треть больше, чем эти 10 символов), так что я как-то неправильно выполняю вызов декодирования ??

И вдобавок ко всему, значения хэширования пароля SHA-1 в PHP имеют длину 40 символов (в базе данных mysql UTF-8) примерно так: dd94709528bb1c83d08f3088d4043f4742891f4f?

Ответы [ 3 ]

5 голосов
/ 22 января 2011

[B@14e1f2b определенно не хэш. Это результат неявного преобразования из byte[] в String.

Похоже, вы делаете что-то вроде этого:

String decodedHash = Base64().decode(hash); // Produces [B@14e1f2b

Однако правильное представление хеша - это байтовый массив:

byte[] decodedHash = Base64().decode(hash); 
3 голосов
/ 22 января 2011

То, что я обычно делаю с Java для вычисления хэша SHA-1, который точно идентичен функции PHP sha1 (), заключается в следующем.Ключ в том, что toHexString используется для показа необработанных байтов печатным способом.Если вы используете функцию PHP и хотите получить тот же результат вашего сложного процесса, вам нужно использовать параметр $ raw_output для true в PHP, чтобы получить необработанные байты и применить Base64. Полный исходный код .

/**
 * Compute a SHA-1 hash of a String argument
 *
 * @param arg the UTF-8 String to encode
 * @return the sha1 hash as a string.
 */
public static String computeSha1OfString(String arg) {
    try {
        return computeSha1OfByteArray(arg.getBytes(("UTF-8")));
    } catch (UnsupportedEncodingException ex) {
        throw new UnsupportedOperationException(ex);
    }
}

private static String computeSha1OfByteArray(byte[] arg) {
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.update(arg);
        byte[] res = md.digest();
        return toHexString(res);
    } catch (NoSuchAlgorithmException ex) {
        throw new UnsupportedOperationException(ex);
    }
}

private static String toHexString(byte[] v) {
    StringBuilder sb = new StringBuilder(v.length * 2);
    for (int i = 0; i < v.length; i++) {
        int b = v[i] & 0xFF;
        sb.append(HEX_DIGITS.charAt(b >>> 4)).append(HEX_DIGITS.charAt(b & 0xF));
    }
    return sb.toString();
}
1 голос
/ 22 января 2011

PHP sha1 () кодирует каждый байт вывода как шестнадцатеричный по умолчанию, но вы можете получить необработанный вывод, передав true в качестве второго аргумента:

$digest = sha1($password, true); // This returns the same string of bytes as md.digest()

Затем передайте дайджест по base64_encode и все готово:

base64_encode(sha1($password, true));

Возвращает тот же хэш SHA-1, что и ваш код Java.

...