Обробка паролів, що використовуються для автентифікації у вихідному коді


79

Якщо припустити, що я намагаюся отримати з RESTful API, який використовує базову автентифікацію / основні сертифікати, який найкращий спосіб зберегти це ім'я користувача та пароль у моїй програмі? Зараз це просто сидить там у відкритому тексті.

UsernamePasswordCredentials creds = new UsernamePasswordCredentials("myName@myserver","myPassword1234");

Чи є якийсь спосіб зробити це, що більше стосується безпеки?

Дякую


4
Відповідь залежить від наступних речей: Ви хочете поширювати програму? Користувач / пароль базується на користувачі програми, чи це якийсь ключ API? Ви хочете захистити користувача / пароль від локального користувача (якийсь DRM)?
parasietje

Це насправді програма, що працює на серверній системі, але насправді вона більше стосується стилю. Я не повинен мати Ім'я користувача / Пароль для облікового запису, в якому зберігається інформація секретного рівня у відкритому тексті.
A_Elric

2
погляньте на цю тему stackoverflow.com/questions/12198228/… і ви отримаєте загальну ідею.
Акула

Відповіді:


112

Важлива примітка:

Якщо ви розробляєте систему автентифікації в цілому, вам не слід зберігати паролі, навіть якщо вони зашифровані. Ви зберігаєте хеш і перевіряєте, чи відповідають паролі, введені під час входу, тому самому хешу. Таким чином, порушення безпеки вашої бази даних дозволяє уникнути виявлення паролів ваших користувачів.

З огляду на це, з внутрішньо-зовнішнім мисленням, ось кілька кроків для захисту вашого процесу:


Першим кроком, вам слід змінити обробку паролів з Stringна character array.

Причиною цього є те, що a Stringє immutableоб'єктом, і тому його дані не будуть очищені відразу, навіть якщо для об'єкта встановлено значення null; Натомість дані встановлені для збору сміття, і це створює проблеми із безпекою, оскільки шкідливі програми можуть отримати доступ до цих String(парольних) даних перед тим, як їх очистити.

Це основна причина, чому метод JPasswordField SwinggetText() застарілий, і чому getPassword()використовуються масиви символів .


Другий крок - це шифрування ваших облікових даних, лише тимчасове їх розшифрування під час процесу автентифікації. Або хешувати їх на стороні сервера, зберігати цей хеш і "забувати" оригінальний пароль.

Це, подібно до першого кроку, гарантує, що час вразливості є якомога меншим.

Рекомендується, щоб ваші облікові дані не були жорстко закодовані, а замість цього ви зберігали їх у централізованому, конфігуруваному та легко підтримуваному способі, наприклад, у файлі конфігурації чи властивостей або в базі даних.

Перед збереженням файлу слід зашифрувати свої облікові дані, а крім того, ви можете застосувати друге шифрування до самого файлу (2-шарове шифрування до облікових даних та 1-шарове до іншого вмісту файлу).

Зверніть увагу, що кожен із двох згаданих вище процесів шифрування може бути багатошаровим. Кожне шифрування може бути окремим додатком стандарту потрійного шифрування даних (AKA TDES та 3DES) , як концептуальний приклад.


Після того, як ваше локальне середовище буде належним чином захищене (але пам’ятайте, воно ніколи не буде «безпечним»!), Третім кроком є ​​застосування базового захисту до вашого процесу передачі за допомогою TLS (Transport Layer Security) або SSL (Secure Sockets Layer) .


Четвертим кроком є ​​застосування інших методів захисту.

Наприклад, застосовуючи прийоми затухання до вашої компіляції "для використання", щоб уникнути (навіть невдовзі) впливу ваших заходів безпеки у випадку, якщо ваша програма отримана пані Євою, містером Меллорі або кимось іншим (погано хлопці) і декомпілювали.


ОНОВЛЕННЯ 1:

За запитом @ Damien.Bell, ось приклад, який охоплює перший та другий кроки:

    //These will be used as the source of the configuration file's stored attributes.
    private static final Map<String, String> COMMON_ATTRIBUTES = new HashMap<String, String>();
    private static final Map<String, char[]> SECURE_ATTRIBUTES = new HashMap<String, char[]>();
    //Ciphering (encryption and decryption) password/key.
    private static final char[] PASSWORD = "Unauthorized_Personel_Is_Unauthorized".toCharArray();
    //Cipher salt.
    private static final byte[] SALT = {
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,};
    //Desktop dir:
    private static final File DESKTOP = new File(System.getProperty("user.home") + "/Desktop");
    //File names:
    private static final String NO_ENCRYPTION = "no_layers.txt";
    private static final String SINGLE_LAYER = "single_layer.txt";
    private static final String DOUBLE_LAYER = "double_layer.txt";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws GeneralSecurityException, FileNotFoundException, IOException {
        //Set common attributes.
        COMMON_ATTRIBUTES.put("Gender", "Male");
        COMMON_ATTRIBUTES.put("Age", "21");
        COMMON_ATTRIBUTES.put("Name", "Hypot Hetical");
        COMMON_ATTRIBUTES.put("Nickname", "HH");

        /*
         * Set secure attributes.
         * NOTE: Ignore the use of Strings here, it's being used for convenience only.
         * In real implementations, JPasswordField.getPassword() would send the arrays directly.
         */
        SECURE_ATTRIBUTES.put("Username", "Hypothetical".toCharArray());
        SECURE_ATTRIBUTES.put("Password", "LetMePass_Word".toCharArray());

        /*
         * For demosntration purposes, I make the three encryption layer-levels I mention.
         * To leave no doubt the code works, I use real file IO.
         */
        //File without encryption.
        create_EncryptedFile(NO_ENCRYPTION, COMMON_ATTRIBUTES, SECURE_ATTRIBUTES, 0);
        //File with encryption to secure attributes only.
        create_EncryptedFile(SINGLE_LAYER, COMMON_ATTRIBUTES, SECURE_ATTRIBUTES, 1);
        //File completely encrypted, including re-encryption of secure attributes.
        create_EncryptedFile(DOUBLE_LAYER, COMMON_ATTRIBUTES, SECURE_ATTRIBUTES, 2);

        /*
         * Show contents of all three encryption levels, from file.
         */
        System.out.println("NO ENCRYPTION: \n" + readFile_NoDecryption(NO_ENCRYPTION) + "\n\n\n");
        System.out.println("SINGLE LAYER ENCRYPTION: \n" + readFile_NoDecryption(SINGLE_LAYER) + "\n\n\n");
        System.out.println("DOUBLE LAYER ENCRYPTION: \n" + readFile_NoDecryption(DOUBLE_LAYER) + "\n\n\n");

        /*
         * Decryption is demonstrated with the Double-Layer encryption file.
         */
        //Descrypt first layer. (file content) (REMEMBER: Layers are in reverse order from writing).
        String decryptedContent = readFile_ApplyDecryption(DOUBLE_LAYER);
        System.out.println("READ: [first layer decrypted]\n" + decryptedContent + "\n\n\n");
        //Decrypt second layer (secure data).
        for (String line : decryptedContent.split("\n")) {
            String[] pair = line.split(": ", 2);
            if (pair[0].equalsIgnoreCase("Username") || pair[0].equalsIgnoreCase("Password")) {
                System.out.println("Decrypted: " + pair[0] + ": " + decrypt(pair[1]));
            }
        }
    }

    private static String encrypt(byte[] property) throws GeneralSecurityException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));

        //Encrypt and save to temporary storage.
        String encrypted = Base64.encodeBytes(pbeCipher.doFinal(property));

        //Cleanup data-sources - Leave no traces behind.
        for (int i = 0; i < property.length; i++) {
            property[i] = 0;
        }
        property = null;
        System.gc();

        //Return encryption result.
        return encrypted;
    }

    private static String encrypt(char[] property) throws GeneralSecurityException {
        //Prepare and encrypt.
        byte[] bytes = new byte[property.length];
        for (int i = 0; i < property.length; i++) {
            bytes[i] = (byte) property[i];
        }
        String encrypted = encrypt(bytes);

        /*
         * Cleanup property here. (child data-source 'bytes' is cleaned inside 'encrypt(byte[])').
         * It's not being done because the sources are being used multiple times for the different layer samples.
         */
//      for (int i = 0; i < property.length; i++) { //cleanup allocated data.
//          property[i] = 0;
//      }
//      property = null; //de-allocate data (set for GC).
//      System.gc(); //Attempt triggering garbage-collection.

        return encrypted;
    }

    private static String encrypt(String property) throws GeneralSecurityException {
        String encrypted = encrypt(property.getBytes());
        /*
         * Strings can't really have their allocated data cleaned before CG,
         * that's why secure data should be handled with char[] or byte[].
         * Still, don't forget to set for GC, even for data of sesser importancy;
         * You are making everything safer still, and freeing up memory as bonus.
         */
        property = null;
        return encrypted;
    }

    private static String decrypt(String property) throws GeneralSecurityException, IOException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
        return new String(pbeCipher.doFinal(Base64.decode(property)));
    }

    private static void create_EncryptedFile(
                    String fileName,
                    Map<String, String> commonAttributes,
                    Map<String, char[]> secureAttributes,
                    int layers)
                    throws GeneralSecurityException, FileNotFoundException, IOException {
        StringBuilder sb = new StringBuilder();
        for (String k : commonAttributes.keySet()) {
            sb.append(k).append(": ").append(commonAttributes.get(k)).append(System.lineSeparator());
        }
        //First encryption layer. Encrypts secure attribute values only.
        for (String k : secureAttributes.keySet()) {
            String encryptedValue;
            if (layers >= 1) {
                encryptedValue = encrypt(secureAttributes.get(k));
            } else {
                encryptedValue = new String(secureAttributes.get(k));
            }
            sb.append(k).append(": ").append(encryptedValue).append(System.lineSeparator());
        }

        //Prepare file and file-writing process.
        File f = new File(DESKTOP, fileName);
        if (!f.getParentFile().exists()) {
            f.getParentFile().mkdirs();
        } else if (f.exists()) {
            f.delete();
        }
        BufferedWriter bw = new BufferedWriter(new FileWriter(f));
        //Second encryption layer. Encrypts whole file content including previously encrypted stuff.
        if (layers >= 2) {
            bw.append(encrypt(sb.toString().trim()));
        } else {
            bw.append(sb.toString().trim());
        }
        bw.flush();
        bw.close();
    }

    private static String readFile_NoDecryption(String fileName) throws FileNotFoundException, IOException, GeneralSecurityException {
        File f = new File(DESKTOP, fileName);
        BufferedReader br = new BufferedReader(new FileReader(f));
        StringBuilder sb = new StringBuilder();
        while (br.ready()) {
            sb.append(br.readLine()).append(System.lineSeparator());
        }
        return sb.toString();
    }

    private static String readFile_ApplyDecryption(String fileName) throws FileNotFoundException, IOException, GeneralSecurityException {
        File f = new File(DESKTOP, fileName);
        BufferedReader br = new BufferedReader(new FileReader(f));
        StringBuilder sb = new StringBuilder();
        while (br.ready()) {
            sb.append(br.readLine()).append(System.lineSeparator());
        }
        return decrypt(sb.toString());
    }

Повний приклад, що стосується кожного кроку захисту, набагато перевищує те, що, на мою думку, є розумним для цього питання, оскільки мова йде про "які етапи" , а не "як їх застосовувати" .

Це могло б значно перевищити мою відповідь (нарешті, вибірку), тоді як інші питання тут, на тему SO, вже спрямовані на те, "як робити" ці кроки, будучи набагато більш доречними, і пропонуючи набагато кращі пояснення та вибірку щодо впровадження кожен окремий крок.


3
[*]- @ Damien.Bell Щоб не залишити ваш запит без уваги, я включив приклад, який охоплює перший (~) та другий кроки. --- Що стосується того, чому не всі кроки, ну, як ви бачите, це не те, що ви можете взяти за допомогою маленького маленького фрагмента коду; А приклад для захисту мережі потребує навіть більше, ніж місцевий обсяг, навіть якщо він частково псевдокодований. Обфускація також має дуже широкий спектр методів реалізації, і хоча це просто за задумом, той факт, що він застосовується до самого вихідного коду, означає, що це важко пояснити у зразках.
XenoRo

2
Нарешті, запустіть на своєму джерелі інструмент обфускації, такий як ProGuard. Байтовий код Java, як відомо, легко розібрати та проаналізувати. Заплутаність є вишнею на вашому торті безпеки, і це набагато ускладнює комусь інженерну розробку вашого коду та потенційно зламати ваші заходи безпеки. Див .: proguard.sourceforge.net/index.html#manual/introduction.html
Джаррод Сміт

1
@ Woot4Moo - Наскільки я розумію, оскільки він намагається взяти з нелокальної сутності (сервера), сфера дії полягає не в процесі аутентифікації з точки зору автентифікатора (сервера), а з клієнтської. --- Таким чином, клієнт повинен захищати облікові дані при зберіганні та передачі, але надсилати ці дані як вони є . Безпека передачі здійснюється на 3-му етапі, який за своєю суттю має шифрування, хешування та перетравлення повідомлень. ___ Сервер - це місце, де застосовується таке порівняння хеш-функцій, і клієнт не повинен виконувати сервісні процеси з міркувань безпеки.
XenoRo

1
@Roland Я не програмував нічого на Java останній рік чи близько того, тому я не пам’ятаю про те, що було б CharBufferспеціально зафіксовано , але, якщо це не є незмінним (можна отримати внутрішні дані, переписані на nullабо нулі без чекаючи GC), ви можете використовувати його, якщо не забудете очистити.
XenoRo 02.03.17

1
Маючи всю інформацію про дешифрування та шифрування (включаючи сіль) у своєму вихідному коді, як це безпечніше?
Herr Derb

7

Якщо ви використовуєте базову автентифікацію, вам слід поєднати це з SSL, щоб уникнути передачі своїх облікових даних у простому тексті, закодованому base64. Ви не хочете, щоб хтось нюхав ваші пакети, щоб отримати ваші облікові дані. Крім того, не кодуйте свої облікові дані у своєму вихідному коді. Зробіть їх налаштованими. прочитати їх з конфігураційного файлу. Вам слід зашифрувати облікові дані, перш ніж зберігати їх у файлі конфігурації, а програма повинна розшифрувати облікові дані, як тільки прочитає їх із конфігураційного файлу.


1
Чи можете ви навести кілька прикладів того, як би ви це робили програмно?
A_Elric


1

Як правило, не є доброю порадою шифрувати облікові дані. Щось, що зашифровано, можна розшифрувати. Найпоширенішою практикою є зберігання паролів як засоленого хешу . Хеш не можна розшифрувати. Сіль додається, щоб перемогти грубу силу вгадування за допомогою Веселкових Столів . Поки кожен UserId має власну випадкову сіль, зловмисникові доведеться створити набір таблиць для кожного можливого значення солі, швидко роблячи цю атаку неможливою протягом тривалості життя Всесвіту. Це причина, через яку веб-сайти зазвичай не можуть надіслати вам ваш пароль, якщо ви його забули, але вони можуть лише "скинути" його. У них не зберігається ваш пароль, лише його хеш.

Хешування паролів не дуже складно реалізувати самостійно, але вирішити настільки типову проблему, що незліченна кількість людей зробили це за вас. Я знайшов jBcrypt простим у використанні.

Як додатковий захист від грубої сили вгадування паролів, загальноприйнятою практикою є змусити userId або віддалений IP зачекати кілька секунд після певної кількості спроб входу за допомогою неправильного пароля. Без цього зловмисник грубої сили може вгадати стільки паролів за секунду, скільки може обробити ваш сервер. Існує величезна різниця між можливістю вгадати 100 паролів за 10 секунд або мільйон.

У мене складається враження, що ви включили комбінацію ім’я користувача / пароль у свій вихідний код. Це означає, що якщо ви коли-небудь захочете змінити пароль, вам доведеться перекомпілювати, зупинити та перезапустити службу, а також означає, що кожен, хто отримає ваш вихідний код, також має ваші паролі. Найпоширенішою практикою є ніколи не робити цього, а зберігати облікові дані (ім’я користувача, хеш пароля, сіль пароля) у вашому сховищі даних


2
Я все ще не впевнений, але я думаю, що "... я намагаюся витягнути з RESTful api ..." означає, що OP не говорить про середовище на стороні сервера. На мою думку, він говорить про програму на стороні клієнта, яка аутентифікується на сервері. __ Таким чином, клієнтська сторона повинна захищати лише облікові дані, що зберігаються (шифрування), і надійно надсилати їх на сервер (TSL / SSL - які за своєю суттю застосовують шифрування та перебір повідомлень) ___ Дайджест повідомлення (для реєстрації або порівняння) ) слід робити лише на стороні сервера, оскільки в іншому випадку це буде небезпечно. ___ Це все в коментарях моєї відповіді.
XenoRo

Крім того, ваша відповідь вказує на використання можливо застарілого API (jBcrypt - це на бета-версії v0.3 і востаннє оновлено в січні 2010 року, що є можливим свідченням того, що проект вимер). Java вже має власні стандартні класи перетравлення повідомлень , і я не думаю, що існує суттєва потреба у сторонніх API.
XenoRo

Схоже, ви маєте рацію щодо плутанини на стороні клієнта та сервера. Я все одно рекомендую зберігати облікові дані в сховищі даних, а не у вихідному коді, але ви маєте рацію щодо того, що вам потрібно шифрування, а не хешування в такому випадку.
Mzzl

Bcrypt - це не дайджест повідомлень, а схема генерації ключів на основі Blowfish. Я використовую його як частину SpringSecurity, яка дуже жива. Звичайні алгоритми дайджестів повідомлень, такі як SHA-1 або MD5, призначені не для хешування паролів, а для швидкого хешування. Якщо вам потрібно якомога швидше хешувати фрагменти відео чи тексту, ви можете скористатися цими або їх сучаснішими замінами. Якщо вас цікавить хешування паролів, швидкість - ваш ворог. Чим швидше використовується алгоритм хешування, тим швидше може бути успішною атака грубої сили.
Mzzl

Хм Деякі пошуки в Google пропонують мені Blowfish - це шифрування (дешифрування), тоді як сторінка jBcrypt вказує, що використовує заснований на Blowfish повідомлення-дайджест ( криптографічна хеш-функція ) ... Я збентежений. ___ SpringSecurity живий, Bcrypt може не бути; це окремі проекти. ___ У будь-якому випадку, Java 1.7 вже включає в себе шифр blowfish, а модульна структура класу Security забезпечує його досить просту реалізацію, security.Providerнавіть у старих версіях, тому я все ще не бачу потреби в сторонніх API.
XenoRo

1
  1. захищений комп'ютер, який ініціалізує запит (ваш комп'ютер). якщо ця машина небезпечна, вас ніщо не захистить. це абсолютно окрема тема (сучасне програмне забезпечення, правильно налаштована, надійні паролі, зашифрований обмін, апаратні знімки, фізична безпека тощо)
  2. захистіть своє сховище носій, який ви використовуєте для зберігання своїх облікових даних, повинен бути зашифрований. розшифровані облікові дані слід зберігати лише в оперативній пам'яті захищеної машини
  3. люди, які вважають, що апаратному забезпеченню слід довіряти (мабуть, найслабше посилання)
  4. вони також повинні знати якомога менше. це захист від криптоаналізу гумових шлангів
  5. ваші облікові дані повинні виконувати всі рекомендації щодо безпеки (належної довжини, випадковості, єдиної мети тощо)
  6. ваше підключення до віддаленої служби повинно бути захищеним (SSL тощо)
  7. Вашій віддаленій службі слід довіряти (див. пункти 1-4). плюс це повинно бути схильним до злому (якщо ваші дані / служба небезпечні, то захищати ваші облікові дані безглуздо). крім того, він не повинен зберігати ваші облікові дані

плюс, мабуть, тисячі речей, про які я забув :)


Ваша відповідь охоплює як клієнтські, так і серверні етапи захисту узагальненим, але дуже чітким і "наступним" способом. Мені це дуже сподобалось! [+1] --- Є кілька речей, які, на мою думку, слід пояснити лише трохи, а оскільки тут також було декілька проблем з правописом та форматуванням, я взяв на себе свободу редагувати. --- Загальна структура, як і більша частина тексту, незмінна. Я просто додав те, що, на мою думку, не вистачає, та реорганізував існуючий текст, щоб відповідати цьому. Сподіваюся, ви не проти.
XenoRo

я не проти орфографії, посилань, граматики тощо. дякую за це. однак, якщо ви хочете додати щось plz, не змінюйте мою відповідь. якщо ви відчуваєте, що чогось не вистачає, додайте коментар або створіть власну відповідь. я волію підписувати лише своїми словами
piotrek

Я розумію. --- Ну, моя редакція насправді жодним чином не змінила значення вашої відповіді. Здебільшого це було виправлення орфографії та форматування, а форматування, яке потребує виправлення, вимагає незначних змін тексту. Кілька додаткових пояснень були лише продовженням того, про що вже йшлося. --- У будь-якому випадку, будь ласка, виправте орфограму (головна проблема - це головна проблема при запуску фрази) та форматуйте (правильно відокремте "тему" від "вмісту"), застосувавши до тексту відповідні коригування. Також дивіться "схильний" №7 . --- І, звичайно, було б непогано врахувати додаткове.
XenoRo

-1

Якщо ви не можете довіряти середовищу, в якому працює ваша програма, але вам потрібно пройти автентифікацію за допомогою простих паролів або сертифікатів, ви нічого не можете зробити для захисту своїх облікових даних. Найбільше, що ви можете зробити, це затуманити їх методами, описаними в інших відповідях.

Як обхідний шлях, я б запустив усі запити до RESTful api через проксі-сервер, якому ви можете довіряти, і здійснити автентифікацію пароля чистого тексту звідти.


"Якщо ви не можете довіряти середовищу, в якому працює ваша програма, ..., ви нічого не можете зробити для захисту своїх облікових даних." - Якби це було правдою, майже кожна програма, яка має опцію "автозаповнення" для облікових даних, мала б дуже глибокі проблеми. ___ Багато двосторонніх програм (це питання?), Таких як багатокористувацькі ігри та веб-програми, зберігають облікові дані локально, і вони рідко мають серйозні проблеми з безпекою. ___ Дані ніколи не бувають на 100% безпечними, незалежно від середовища. Довірене середовище - це лише черговий крок безпеки ("безпечніший").
XenoRo

Ну, у наведеному сценарії ви можете заплутати свої облікові дані, але не досягти 100% (криптографічної) безпеки. Найбільше, на що ви можете сподіватися, зробити так, щоб зловмисник настільки ускладнив отримання чітких текстових паролів, що не варто їхніх зусиль. Все, що потрібно для отримання збережених паролів типового веб-додатку, це перейти в меню параметрів вашого браузера та вибрати "показати паролі".
Twilite

Ви ніколи не зможете досягти 100% безпеки, будь то в цьому чи будь-якому іншому сценарії . Це пояснюється тим, що врешті-решт все зводиться до послідовностей 0і 1в пам'яті, що досягається за певним набором логічних правил, які за своєю суттю завжди якимось чином оборотні. ___ Основою криптографічної безпеки є, завжди була і, мабуть, буде завжди, "робити це настільки складно, що не варто витрачати зусилля". ___ Нарешті, ви помиляєтесь із автоматичним заповненням / входом браузера (що стосується веб-сайтів) із автоматичним авторизацією / входом програми (який зберігається у зашифрованих файлах і лише там).
XenoRo

Вам слід прочитати про криптографію. Існують різні методи безповоротного шифрування даних, просто подивіться на «хеші в один бік» (md5) або криптографію з відкритим ключем, де неможливо розшифрувати зашифровані дані, навіть якщо у вас є як зашифровані дані, так і ключ шифрування. За допомогою цих методів ви отримуєте фактичну 100% безпеку.
Twilite

Насправді ні. - Як я вже сказав, методи дотримуються певного набору логічних правил, і у них є спосіб змінити. ___ У випадку криптографічних хеш-функцій, якщо хакер знає набір правил, що генерували хеш, він може ВІДБИТИ кілька бітів вихідних даних і отримати чітке загальне уявлення про те, якою може бути довжина оригіналу. --- Це багато форсування грубих і здогадок, але це не на 100% незламно. І це далеко не безкінечна кількість спроб 100% безпеки ___ Я не думаю, що будь-який хакер буде турбуватись жорсткими намаганнями; Це далеко не варті зусилля, незалежно від винагороди.
XenoRo

-1

чому люди говорять про хешування. OP хоче зберігати облікові дані своїх користувачів для доступу до зовнішнього ресурсу. Хешування його пароля не допоможе.

Зараз це зі шляху. Я б просто прості найкращі практики для кожного шару.

1. Зберігання пароля в програмі Java. : Зберігайте як Char Array. Створіть клас зберігання паролів і збережіть пароль як хеш-карту з ключем як ресурсом, до якого ви хочете отримати доступ, і визначте його як об’єкт, що містить ім’я користувача та пароль. Обмежте точку входу до цього API з деякою автентифікацією Приклад: прийміть облікові дані користувачів, що увійшли, щоб перевірити рівень доступу цього користувача до цього ресурсу (просто відобразіть користувача до списку паролів, до яких вони можуть отримати доступ. Якщо вас багато, створіть групу і зіставити ключ мапи пароля з цією групою) Будь-що поза цим, щоб зберігати пароль, залежить від того, наскільки параноїчно ви налаштовані на те, щоб сам jvm його просочив.

  1. для передачі пароля переконайтеся, що ви надсилаєте його на захищені портали (Наприклад: Https - це добре, http - погано). Якщо вам дійсно потрібно передати через незахищений протокол, зашифруйте його та закодуйте, щоб сказати base64. Переконайтеся, що одержувач розшифровує і може розшифрувати ваш пароль.

У ОП була ситуація зберігання облікових даних, але це не було питання. Оператор спеціально запитував про безпеку. => "Чи є спосіб зробити це більш безпечним?"
XenoRo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.