2015-05-28 2 views
0

Учитывая эту строку: ÑIóÝ7áÔtV†°dvÔ抄!Ï­=4à)µ Å!Úã̓¸§cî£ÖošaUÕÝ€÷÷p³6ò¥ˆa, генерируется SecureRandom со следующим способом:Base64 Linux и Windows,

public String getSalt() throws UnsupportedEncodingException { 
    String salt = null; 

    SecureRandom random = new SecureRandom(); 
    byte[] saltArr = new byte[64]; 
    random.nextBytes(saltArr); 

    salt = new String(saltArr).trim(); 

    return salt; 
} 

TLDR: прокручивать вниз

Затем возвращается строка «отформатированные», чтобы избежать специальных символов :

String salt = getSalt(); 
salt = salt.replace("<", "!"); 
salt = salt.replace(">", "!"); 
salt = salt.replace("\"", "!"); 
salt = salt.replace("'", "!"); 
salt = salt.replace("\\", "!"); 
salt = salt.replace("&", "!"); 

Кодирование соли:

public String getEncryptedSalt(String chain) throws UnsupportedEncodingException { 
    byte[] bytes = chain.getBytes(); 
    byte[] encodedBytes = Base64.encodeBase64(bytes); 
    String salt = new String(encodedBytes); 

    return salt; 
} 

Декодирование соль:

public String getDecryptedSalt(String chain) throws UnsupportedEncodingException { 
    byte[] bytes = chain.getBytes(); 
    byte[] decodedBytes = Base64.decodeBase64(bytes); 
    String decrypted = new String(decodedBytes); 

    return decrypted; 
} 

хэширования пароля (декодируется соль + PWD):

public String getHash(String target) throws NoSuchAlgorithmException { 
    MessageDigest sh = MessageDigest.getInstance("SHA-512"); 
    sh.update(target.getBytes()); 
    StringBuilder sb = new StringBuilder(); 
    for (byte b : sh.digest()) { 
     sb.append(Integer.toHexString(0xff & b)); 
    } 

    return sb.toString(); 
} 

Почему я получаю разные результаты на одной и той же строке (выше) на разных ОС ?

Пример кода:

String salt = "ÑIóÝ7áÔtV†°dvÔ抄!Ï­=4à)µ Å!Úã̓¸§cî£ÖošaUÕÝ€÷÷p³6ò¥ˆ`a,"; 
String encodedSalt = getEncryptedSalt(salt); 
String decodedSalt = getDecryptedSalt(encodedSalt); 
String pwd = "AbcD12345"; 
String hashed = getHash(salt+pwd); 

Windows, пример:

SALT: ÑIóÝ7áÔtV†°dvÔ抄!Ï­=4à)µ Å!Úã̓¸§cî£ÖošaUÕÝ€÷÷p³6ò¥ˆ`a, 
SALT ENCODED: 0Unz3TfhAx3UdFaGsGR21OaKhCHPrT004Cm1IBnFIdrjzYO4p2Puo9ZvmmFV1RndgPcb93CzAgg28qWIYGEDLA== 
SALT DECODED: ÑIóÝ7áÔtV†°dvÔ抄!Ï­=4à)µ Å!Úã̓¸§cî£ÖošaUÕÝ€÷÷p³6ò¥ˆ`a, 

PWD: AbcD12345 
SALT+PWD: b0d87c79895a59bb52227eaf4aac01437676c3494a5493690c87b76efbe260e41082b6c53d811e8de4c612142eca82b970d6bba42e71cc90efa26c74e08155 

Linux - Debian7 пример:

SALT: ÑIóÝ7áÔtV†°dvÔ抄!Ï­=4à)µ Å!Úã̓¸§cî£ÖošaUÕÝ€÷÷p³6ò¥ˆ`a, 
SALT ENCODED: w5FJw7PDnTfDoQMdw5R0VuKAoMKwZHbDlMOmxaDigJ4hw4/CrT00w6ApwrUgGcOFIcOaw6PDjcaSwrjCp2PDrsKjw5ZvxaFhVcOVGcOd4oKsw7cbw7dwwrMCCDbDssKly4ZgYQMs 
SALT DECODED: ÑIóÝ7áÔtV†°dvÔ抄!Ï­=4à)µ Å!Úã̓¸§cî£ÖošaUÕÝ€÷÷p³6ò¥ˆ`a, 

PWD: AbcD12345 
SALT+PWD: e0c31f603f36a6d1c5db1a64ebe01bbc3d51f0544d319535bbf8c345a1b7fe2fb68a98d1175a98eedf26e1a441528583a4cc285954e26a56f9d23d7174ea2 

Даже жесткая соль одинакова на обеих системах, кодируемый соли различны, но декодированные соли одинаковы, почему? Почему это влияет на пароль, если его единственная строковая сумма соли + пароль?

PD: По меньшей мере, я не понимаю, что: соль и pwd сохраняются в базе данных MySQL. Если я создаю пользователя в Windows, тогда экспортируйте базу данных в Linux, он не сможет аутентифицироваться из-за неправильного пароля. Но если тогда я создаю пользователя в Linux и экспортирую базу данных в Windows, то сможет авторизоваться ...

+1

'Base64' не имеет ничего общего с шифрованием и дешифровкой – specializt

+0

@specializt ok, тогда почему хеши разные? Кстати, как я назвал методы – Alpha2k

ответ

1

Вы используете new String(bytes) в ряде мест. Это будет интерпретировать байты и преобразовать их в символы с использованием по умолчанию character encoding вашей системы.

Кодировка символов по умолчанию в Windows отличается от кодировки символов по умолчанию в Linux, поэтому результаты будут разными.

Избегайте использования кодировки по умолчанию; явно укажите кодировку символов. Например:

salt = new String(saltArr, "UTF-8").trim(); 

String salt = new String(encodedBytes, "UTF-8"); 

String decrypted = new String(decodedBytes, "UTF-8"); 

редактировать Даже если вы сделаете это, это, вероятно, не будет работать:

SecureRandom random = new SecureRandom(); 
byte[] saltArr = new byte[64]; 
random.nextBytes(saltArr, "UTF-8"); 

Вы генерации случайных байт, а затем вы интерпретируете эти байты, как если бы они закодированные символы (с использованием некоторой кодировки символов). Это может вызвать исключение, если случайные байты являются, например, недопустимыми последовательностями UTF-8.

Строки не подходят в качестве контейнеров для случайных байтов. Не пытайтесь создавать строки из случайных байтов таким образом. Вместо этого выполните базовую кодировку до, вы поместите байты в String. Или генерировать случайные символов вместо случайных байт для соли.

+0

, если я использую UTF-8 для соли, я получаю еще более странный результат, пробовал и не работает, Salt as UTF8 co gl |^! .d | ͬ zE Y h 鮰 A, ! 5 ~ $ k M – Alpha2k

+0

Я в конечном итоге, как я сначала, создаю то, что не должно зависеть от системных переменных. Вероятно, вместо base64 было бы проще использовать нечто вроде AES и создать случайную соль как простые числа и буквы. – Alpha2k

+1

Кроме того, 'string.getBytes()' имеет ту же проблему в другом направлении. –

0

Изменена соль из:

public String getSalt() throws UnsupportedEncodingException { 
String salt = null; 

SecureRandom random = new SecureRandom(); 
byte[] saltArr = new byte[64]; 
random.nextBytes(saltArr); 

salt = new String(saltArr).trim(); 

return salt; 
} 

Для

public String getSalt() throws UnsupportedEncodingException { 
    return new BigInteger(130, new SecureRandom()).toString(32); 
} 

Менее сложные, но меньше ошибок.

Смежные вопросы