Генератор випадкових паролів

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Генератор випадкових паролів — це програмне забезпечення або апаратний пристрій, який отримує вхідні дані від генератора випадкових чи псевдовипадкових чисел і автоматично генерує пароль. Випадкові паролі можна згенерувати вручну, використовуючи прості джерела випадковості, такі як кубики[en] чи монети, або їх можна створити за допомогою комп'ютера.

Хоча в Інтернеті є багато прикладів програм для генерування «випадкових» паролів, генерація випадкових паролів може бути складною, і багато програм не генерують випадкові символи таким чином, щоб забезпечити надійну безпеку. Загальною рекомендацією є використання інструментів безпеки з відкритим кодом де це можливо оскільки вони дозволяють незалежно перевіряти якість використовуваних методів. Зауважте, що просте генерування пароля навмання не гарантує, що пароль є надійним, оскільки можливо, хоча й дуже малоймовірно, створити пароль, який легко вгадати або зламати. Насправді немає жодної потреби, щоб пароль створювався абсолютно випадковим процесом: його просто має бути достатньо важко вгадати.

Генератор паролів може бути частиною менеджера паролів. Коли політика паролів[en] забезпечує виконання складних правил, може бути легше використовувати генератор паролів на основі цього набору правил, ніж створювати паролі вручну.

Більшості людей важко запам'ятати довгі рядки випадкових символів. Мнемонічні хеші, які оборотно перетворюють випадкові рядки в паролі, які краще запам'ятовуються, можуть значно покращити легкість запам'ятовування. Оскільки хеш може бути оброблений комп'ютером для відновлення вихідного 60-бітного рядка, він містить принаймні стільки ж інформації, скільки вихідний рядок.[1] Подібні прийоми використовуються в спортивному запам'ятовуванні.

Наївний підхід[ред. | ред. код]

Ось два зразки коду, які програміст, який не знайомий з обмеженнями генераторів випадкових чисел у стандартних бібліотеках програмування, може застосувати:

C[ред. | ред. код]

# include <time.h>
# include <stdio.h>
# include <stdlib.h>

int
main(void)
{
    /* Length of the password */
    unsigned short int length = 8;

    /* Seed number for rand() */
    srand((unsigned int) time(0));

    /* ASCII characters 33 to 126 */
    while (length--) {
        putchar(rand() % 94 + 33);
    }

    printf("\n");

    return EXIT_SUCCESS;
}

У цьому випадку стандартна функція C rand, яка є генератором псевдовипадкових чисел, спочатку заповнюється за допомогою функції C time, але в подальших ітераціях замість неї використовується rand. Відповідно до стандарту ANSI C, time повертає значення типу time_t, яке визначається реалізацією, але найчастіше це 32-розрядне ціле число, що містить поточну кількість секунд з 1 січня 1970 року (див.: час Unix). У році є приблизно 31 мільйон секунд, тому зловмисник, який знає рік (проста справа в ситуаціях, коли часта зміна пароля вимагається політикою паролів) та ідентифікатор процесу, з яким було згенеровано пароль, стикається з відносно невеликою кількістю, за криптографічними стандартами варіантів для тестування. Якщо зловмисник знає точніше, коли був згенерований пароль, він стикається з ще меншою кількістю кандидатів для тестування — серйозний недолік у цій реалізації. 

У ситуаціях, коли зловмисник може отримати зашифровану версію пароля, таке тестування можна виконати досить швидко, щоб кілька мільйонів пробних паролів можна було перевірити за лічені секунди. Дивіться: злом паролів .

Функція rand представляє іншу проблему. Усі генератори псевдовипадкових чисел мають внутрішню пам'ять або стан. Розмір цього стану визначає максимальну кількість різних значень, які він може створити: n -розрядний стан може створити щонайбільше різних значень. У багатьох системах rand має 31 або 32-бітний стан, що вже є значним обмеженням безпеки. Документація Microsoft не описує внутрішній стан реалізації rand стандартної бібліотеки C у Visual C++, але вона має лише 32767 можливих виходів (15 біт) на виклик.[2] Корпорація Microsoft рекомендує використовувати іншу, більш безпечну функцію, rand_s. Вихід rand_s є криптографічно захищеним, згідно з Microsoft, і він не використовує початкове значення, завантажене функцією srand. Однак його інтерфейс програмування відрізняється від rand.[3]

PHP[ред. | ред. код]

function pass_gen(int $length = 8): string
{
    $pass = array();
    for ($i = 0; $i < $length; $i++) {
        $pass[] = chr(mt_rand(32, 126));
    }

    return implode($pass);
}

У другому випадку використовується функція PHP microtime[4], яка повертає поточну позначку часу Unix із мікросекундами. Це збільшує кількість можливостей, але той, хто добре здогадується, коли було згенеровано пароль, наприклад, дату початку роботи працівника, все ще має досить малий простір для пошуку. Крім того, деякі операційні системи не забезпечують час для мікросекундної роздільної здатності, що різко зменшує кількість варіантів. Нарешті, функція rand[5] зазвичай використовує базову функцію C rand і може мати невеликий простір станів, залежно від того, як вона реалізована. Альтернативний генератор випадкових чисел, mt_rand, який базується на генераторі псевдовипадкових чисел вихор Мерсенна, доступний у PHP, але він також має 32-розрядний стан. Є пропозиції щодо додавання сильної генерації випадкових чисел до PHP.[6]

Сильніші методи[ред. | ред. код]

Існує безліч методів генерації надійних, криптографічно безпечних випадкових паролів. На платформах Unix зазвичай використовуються /dev/random і /dev/urandom або програмно, або в поєднанні з такою програмою, як makepasswd.[7] Програмісти Windows можуть використовувати функцію CryptGenRandom з Cryptographic Application Programming Interface[en]. Мова програмування Java включає клас під назвою SecureRandom. Інша можливість полягає в отриманні випадковості шляхом вимірювання якогось зовнішнього явища, наприклад визначення часу введення користувача з клавіатури.

Багато комп'ютерних систем вже мають програму (зазвичай звану «apg») для реалізації FIPS 181.[8] FIPS 181 — Automated Password Generator — описує стандартний процес перетворення випадкових бітів (з апаратного генератора випадкових чисел) у певною мірою вимовні «слова», придатні для парольної фрази.[9] Однак у 1994 році було виявлено атаку на алгоритм FIPS 181, так що зловмисник може розраховувати в середньому на злам 1 % облікових записів, які мають паролі на основі алгоритму, після пошуку лише 1,6 мільйона паролів. Це пов'язано з нерівномірністю розподілу згенерованих паролів, яку можна вирішити, використовуючи довші паролі або змінюючи алгоритм.[10][11]

Bash[ред. | ред. код]

Ось приклад коду, який використовує /dev/urandom для створення пароля за допомогою простої функції Bash . Ця функція приймає довжину пароля як параметр або використовує 16 за замовчуванням:

function mkpw() { LC_ALL=C tr -dc '[:graph:]' < /dev/urandom | head -c ${1:-16}; echo; }

Java[ред. | ред. код]

Ось зразок коду (адаптований з класу PasswordGenerator[12]), який використовує SecureRandom для генерації пароля з 10 шістнадцяткових символів:

char[] symbols = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
int length = 10;
Random random = SecureRandom.getInstanceStrong();    // as of JDK 8, this returns a SecureRandom implementation known to be strong
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
    int randomIndex = random.nextInt(symbols.length);
    sb.append(symbols[randomIndex]);
}
String password = sb.toString();

JavaScript[ред. | ред. код]

У цьому прикладі використовується модуль Node.js Crypto для створення криптографічно захищених випадкових чисел із рівномірним розподілом.

"use strict";

const { randomInt } = require("crypto");

const secret = (length = 64) => {
  const upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  const lowerCase = "abcdefghijklmnopqrstuvwxyz";
  const digits = "0123456789";
  const minus = "-";
  const underline = "_";
  const special = "!\"#$%&'*+,./:;=?@\\^`|~";
  const brackets = "[]{}()<>";
  const all = upperCase + lowerCase + digits + minus + underline + special + brackets;
  let secret = "";
  for (let index = 0; index < length; index++) secret += all.charAt(randomInt(all.length));
  return secret;
};

Perl[ред. | ред. код]

У цьому прикладі використовується модуль Crypt::Random::Source для пошуку джерела сильних випадкових чисел (що залежить від платформи).

use Crypt::Random::Source qw(get_strong);

while(length($out) < 15) {
    my $a = get_strong(1);
    $a =~ s/[^[:graph:]]//g;
    $out .= $a;
}
print $out;

Python[ред. | ред. код]

Мова Python включає клас SystemRandom, який отримує випадкові біти криптографічного рівня з /dev/urandom в Unix-подібній системі, включаючи Linux і macOS, тоді як у Windows він використовує CryptGenRandom.[13][14] Ось простий сценарій Python, який демонструє використання цього класу:

#!/usr/bin/env python3
import random, string
myrg = random.SystemRandom()
length = 10
alphabet = string.ascii_letters + string.digits # a-z A-Z 0-9
password = "".join(myrg.choice(alphabet) for _ in range(length))
print(password)

PHP[ред. | ред. код]

Програма PHP може відкривати та читати з /dev/urandom, якщо доступно, або викликати утиліти Microsoft.[15] Третім варіантом, якщо доступний виклик OpenSSL, є використання функції openssl_random_pseudo_bytes.[16]

Механічні методи[ред. | ред. код]

Ще один метод полягає у використанні фізичних пристроїв, таких як гральні кістки, для створення випадковості. Один простий спосіб зробити це — використання таблиці символів 6 на 6. Перший кидок кубика вибирає рядок у таблиці, а другий — стовпець. Так, наприклад, кидок 2, а потім кидок 4 вибере літеру «j» із таблиці перестановки нижче.[17] Для генерації символів верхнього/нижнього регістру або деяких символів можна використовувати підкидання монети, орел — велика літера, решка — мала. Якщо під час кидання кубиків була вибрана цифра, при підкиданні монети випав орел можна вибрати символ над цифрою на стандартній клавіатурі, наприклад «$» над «4» замість «4».

Тип і надійність згенерованого пароля[ред. | ред. код]

Генератори випадкових паролів зазвичай виводять рядок символів заданої довжини. Це можуть бути окремі символи з певного набору символів, склади, призначені для створення паролів, які можна вимовити, або слова з певного списку слів для створення парольної фрази[en]. Програму можна налаштувати так, щоб кінцевий пароль відповідав місцевій політиці паролів, скажімо, завжди створюючи суміш літер, цифр і спеціальних символів. Такі політики зазвичай знижують міцність трохи нижче наступної формули, оскільки символи більше не створюються незалежно.

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

де N — кількість можливих символів, а L — кількість символів у паролі. Функція log2 є логарифмом за основою 2 . H зазвичай вимірюється в бітах.[18][19]


Ентропія на символ для різних наборів символів
Набір символів Число символів N Ентропія на символ H
Арабські числа (0–9) (напр. PIN) 10 3.32 бітів
Шістнадцяткові числа (0–9, A–F) (напр. ключ WEP) 16 4.00 бітів
Регістрово незалежні[en] літери латинської абетки (a–z або A–Z) 26 4.70 бітів
Регістрово незалежні[en] літероцифрові символи (a–z або A–Z, 0–9) 36 5.17 бітів
Регістрово залежні[en] літери латинської абетки (a–z, A–Z) 52 5.70 бітів
Регістрово залежні[en] літероцифрові символи (a–z, A–Z, 0–9) 62 5.95 бітів
Всі друковані символи ASCII[a] 94 6.55 бітів
Підкидання кубика 7776 12.9 бітів
Довжина L справді випадково згенерованих паролів, необхідних для досягнення бажаної ентропії пароля H для наборів символів, що містять N символів.
Бажана ентропія пароля, H Арабські числа Шістнадцяткові числа Регістрово незалежні[en] літери латинської абетки Регістрово незалежні[en] літероцифрові символи Регістрово залежні[en] літери латинської абетки Регістрово залежні[en] літероцифрові символи Всі друковані символи ASCII[a] Всі символи розширення ASCII[en] Підкидання кубика
32 бітів 10 8 7 7 6 6 5 5 3
40 бітів 13 10 9 8 8 7 7 6 4
64 бітів 20 16 14 13 12 11 10 9 5
80 бітів 25 20 18 16 15 14 13 11 7
96 бітів 29 24 21 19 17 17 15 13 8
128 бітів 39 32 28 25 23 22 20 17 10
160 бітів 49 40 35 31 29 27 25 21 13
192 бітів 58 48 41 38 34 33 30 25 15
224 бітів 68 56 48 44 40 38 35 29 18
256 бітів 78 64 55 50 45 43 40 33 20
384 бітів 116 96 82 75 68 65 59 50 30
512 бітів 155 128 109 100 90 86 79 66 40
1024 бітів 309 256 218 199 180 172 157 132 80
  1. а б За виключенням "пробілу".

Будь-який генератор паролів обмежений простором стану використовуваного генератора псевдовипадкових чисел, якщо він заснований на одному. Таким чином, пароль, згенерований за допомогою 32-бітного генератора, обмежений 32-бітовою ентропією, незалежно від кількості символів, які містить пароль.

Зауважте, однак, що інший тип атаки може бути успішним проти пароля, оціненого як «дуже надійний» за наведеними вище обчисленнями.

Програми та веб-сайти для створення паролів[ред. | ред. код]

В Інтернеті доступна велика кількість програм і веб-сайтів для створення паролів. Їх якість змінюється, і її важко оцінити, якщо немає чіткого опису джерела випадковості, яке використовується, і якщо вихідний код не надається для перевірки тверджень. Більше того, і, мабуть, найважливіше, передача потенційних паролів через Інтернет викликає очевидні занепокоєння щодо безпеки, особливо якщо підключення до програми сайту генерації паролів не захищено належним чином або якщо сайт якимось чином скомпрометовано. Без захищеного каналу[en] неможливо запобігти прослуховування, особливо через публічні мережі, такі як Інтернет. Можливим вирішенням цієї проблеми є створення пароля за допомогою мови програмування на стороні клієнта, наприклад JavaScript. Перевага цього підходу полягає в тому, що згенерований пароль залишається на клієнтському комп'ютері і не передається на зовнішній сервер або з нього.

Див. також[ред. | ред. код]

Примітки[ред. | ред. код]

  1. Ghazvininejad, Marjan; Knight, Kevin (May–June 2015). How to Memorize a Random 60-Bit String. Proceedings of the 2015 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies. Т. Proceedings of the 2015 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies. Denver, Colorado: Association for Computational Linguistics. с. 1569—1575. doi:10.3115/v1/N15-1180.
  2. RAND_MAX. docs.microsoft.com.
  3. Visual Studio 2005 Retired documentation. Microsoft Download Center.
  4. PHP: microtime – Manual. php.net.
  5. PHP: rand – Manual. php.net.
  6. Archived copy. Архів оригіналу за 19 жовтня 2008. Процитовано 17 жовтня 2008.{{cite web}}: Обслуговування CS1: Сторінки з текстом «archived copy» як значення параметру title (посилання)
  7. Linux / UNIX: Generating Random Password With mkpasswd / makepasswd / pwgen. cyberciti.biz. November 2007.
  8. StrongPasswords – Community Help Wiki. help.ubuntu.com. Процитовано 25 березня 2016.
  9. NIST. Automated Password Generator standard FIPS 181
  10. Shay, Richard; Kelley, Patrick Gage; Komanduri, Saranga; Mazurek, Michelle L.; Ur, Blase; Vidas, Timothy; Bauer, Lujo; Christin, Nicolas; Cranor, Lorrie Faith (2012). Correct horse battery staple: Exploring the usability of system-assigned passphrases (PDF). SOUPS '12 Proceedings of the Eighth Symposium on Usable Privacy and Security. doi:10.1145/2335356.2335366.
  11. Ganesan, Ravi; Davies, Chris (1994). A New Attack on Random Pronounceable Password Generators (PDF). Proceedings of the 17th {NIST}-{NCSC} National Computer Security Conference. NIST: 184—197. Процитовано 17 грудня 2014.
  12. Rate my random password generator!. Crypto.
  13. 9.6. random — Generate pseudo-random numbers — Python 3.5.1 documentation. docs.python.org. Процитовано 25 березня 2016.
  14. 16.1. os — Miscellaneous operating system interfaces — Python 3.5.1 documentation. docs.python.org. Процитовано 25 березня 2016.
  15. "Secure" Random Numbers in PHP. What the Daily WTF?. 18 квітня 2010.
  16. PHP: openssl_random_pseudo_bytes – Manual. php.net. Процитовано 25 березня 2016.
  17. Levine, John R., Ed.: Internet Secrets, Second edition, page 831 ff. John Wiley and Sons.
  18. Schneier, B: Applied Cryptography, Second edition, page 233 ff. John Wiley and Sons.
  19. Burr, W. E.; Dodson, D. F.; Polk, W. T. (2006). Electronic Authentication Guideline (PDF). NIST. doi:10.6028/NIST.SP.800-63v1.0.2.

Посилання[ред. | ред. код]