Хеширующая уязвимость - PullRequest
       4

Хеширующая уязвимость

0 голосов
/ 18 декабря 2018

Я хочу добавить немного безопасности в свой проект, поэтому я добавил поле пароля.Чтобы сохранить пароль, я собирался использовать txt и сохранить его там, чтобы добавить немного большей безопасности, я использовал приведенный ниже код для хеширования пароля (их несколько паролей сохранялось таким образом, если это важно).Это всего лишь пример того, как я выполнял хеширование, программа использует текстовые файлы и т. Д.

public static void main(String[] args) throws NoSuchAlgorithmException {

    System.out.println("Enter Password: ");
    Scanner scanner = new Scanner(System.in);
    String enteredPassword = scanner.nextLine();
    String storedPassword = "�D�Ϛ-�UK�c�=�,�}��}��D��Zj>�m";

    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
    messageDigest.update(enteredPassword.getBytes());
    String hashedString = new String(messageDigest.digest());
    System.out.println(hashedString);

    if(storedPassword.equals(hashedString)){
        System.out.println("Passwords Match!");   
    }else{
        System.out.println("Passwords Do Not Match!");
    }
}

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

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

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

Для большей безопасности вы можете замедлить работу, например, с помощью bcrypt или PBKDF2.Некоторые 100 мс не будут заметны для пользователя, но делают грубое принуждение нецелесообразным.

Вот пример с PBKDF2, использующим 100000 итераций SHA-256.Он также использует случайную соль.

SecureRandom random = SecureRandom.getInstanceStrong();
byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("my-secret-password".toCharArray(), salt, 100000, 256);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = f.generateSecret(spec).getEncoded();
Base64.Encoder enc = Base64.getEncoder();
System.out.printf("salt: %s%n", enc.encodeToString(salt));
System.out.printf("hash: %s%n", enc.encodeToString(hash));

Примечание: PBKDF2WithHmacSHA256 доступен с Java 8.


Вот более полный пример:

private static final SecureRandom random = new SecureRandom();

/**
 * One-way encrypts (hashes) the given password.
 * 
 * @param saltpw  the salt (will be generated when null)
 * @param pw      the password to encrypt
 * @return        encrypted salted password
 */
public static String encrypt(String saltpw, String pw) throws GeneralSecurityException {
    byte[] salt;
    if (saltpw == null) {
        salt = new byte[16];
        random.nextBytes(salt);
    } else {
        salt = Base64.getDecoder().decode(saltpw.replaceFirst("\\$.*", ""));
    }
    KeySpec spec = new PBEKeySpec(pw.toCharArray(), salt, 100000, 256);
    SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    byte[] hash = f.generateSecret(spec).getEncoded();
    Base64.Encoder enc = Base64.getEncoder();
    return enc.encodeToString(salt) + "$" + enc.encodeToString(hash);
}

public static void main(String[] args) throws Exception {
    String enc = encrypt(null, "my-secret-password");
    System.out.printf("enc   : %s\n", enc);
    String test1 = encrypt(enc, "my-secret-password");
    System.out.printf("test 1: %s, valid: %b\n", test1, enc.equals(test1));
    String test2 = encrypt(enc, "some-other-password");
    System.out.printf("test 2: %s, valid: %b\n", test2, enc.equals(test2));
}

Печать:

enc   : B5V6SjkjJpeOxvMAkPf7EA==$NNDA7o+Dpd+M+H99WVxY0B8adqVWJHZ+HIjgPxMljwo=
test 1: B5V6SjkjJpeOxvMAkPf7EA==$NNDA7o+Dpd+M+H99WVxY0B8adqVWJHZ+HIjgPxMljwo=, valid: true
test 2: B5V6SjkjJpeOxvMAkPf7EA==$4H1SpH8N+/jqU40G6RWb+ReHUB3C58iAaU4l39j+TV8=, valid: false

Обратите внимание, что test 1 приводит к точно такой же зашифрованной строке, что и исходный пароль, а test 2 (с неверным паролем) - нет.Таким образом, вы можете проверить, является ли предоставленный пароль действительным или нет, просто сравнив хэши.

0 голосов
/ 18 декабря 2018

Нет способа запретить декомпиляцию java.

Но вы можете усложнить понимание декомпилированного кода, если используете обфускатор.Например, https://www.guardsquare.com/en/products/proguard

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...