Генерация случайного пароля

Материал из DRKB


Пароль из определенных символов[править | править код]

function RandomPassword(PLen: Integer): string;
var
  str: string;
begin
  Randomize;
  // string with all possible chars
  str := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  Result := '';
  repeat
    Result := Result + str[Random(Length(str)) + 1];
  until (Length(Result) = PLen);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // generate a password with 10 chars
  Label1.Caption := RandomPassword(10);
end;


Source: http://www.swissdelphicenter.ch
ID: 04032



Пароль из диапазона символов[править | править код]

// Another function from ReNoiZer /=RNZ=/; renoizer@mail.ru
function RandomWord(dictSize, lngStepSize, wordLen, minWordLen: Integer): string;
begin
  Result := '';
  if (wordLen < minWordLen) and (minWordLen > 0) then
    wordLen := minWordLen
  else if (wordLen < 1) and (minWordLen < 1) then
    wordLen := 1;
  repeat
    Result := Result + Chr(Random(dictSize) + lngStepSize);
  until (Length(Result) = wordLen);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  // generate a password with 10 chars
  Caption := RandomWord(33, 54, Random(12), 2);
end;


Source: http://www.swissdelphicenter.ch
ID: 04033



Форма для генерации пароля[править | править код]

Hi всем! Начнём с того что кинем на форму три Edit-а, Батон (Button), два GroopBox-a, PopUp меню и UpDown. На одну панель бросаем три RadioButton-a, на другую три CheckBox-a. Ассоциируем UpDown с первым Edit-ом, здесь будет выбор кол-ва букв в пароле. Второй Edit будет для вывода пароля, а третий для побуквенного вывода сгенереного пароля. CheckBox-ы называем C1,C2,C3,C4,C5. RadioButton-ы называем Ra1,Ra2,Ra3. В меню делаем два пункта, их Caption называем +10 и -10. Caption-ы CheckBox-ов обзываем 'Латиница','Кирилица','0..9','Спецсимволы ' и 'Смесь'. Это для выбора символов из которых генерится пароль. Caption-ы RadioButton-ов обзываем 'Upper Case' 'Lower Case' 'Misc' -для выбора регистра. Один CheckBox и RadioButton делаем выделеными по умолчанию. Батон используем как стартовую кнопку. А дальше смотрите код:


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Spin, ExtCtrls, Menus, ComCtrls, Buttons;

type
  TForm1 = class(TForm)
    Gen: TButton;
    Label1: TLabel;
    Status: TStatusBar;
    PopupMenu2: TPopupMenu;
    N101: TMenuItem;
    N102: TMenuItem;
    edit2: TEdit;
    edit3: TEdit;
    edit1: TMemo;
    U1: TUpDown;
    C1: TCheckBox;
    C2: TCheckBox;
    C3: TCheckBox;
    C4: TCheckBox;
    C5: TCheckBox;
    Ra1: TRadioButton;
    Ra2: TRadioButton;
    Ra3: TRadioButton;
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    procedure GenClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure N101Click(Sender: TObject); { Обработка пунктов меню }
    procedure N102Click(Sender: TObject); { Обработка пунктов меню }
    procedure SpinKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure edit1KeyPress(Sender: TObject; var Key: Char);
  private
    { Private declarations }
  public
    { Public declarations }
end;

var
  Form1: TForm1;
  kol: integer;
  ss: string;

implementation

{$R *.DFM}

procedure TForm1.GenClick(Sender: TObject);
label
  1;
const
  con1 = 'qwertyuiopasdfghjklzxcvbnm';
  con2 = 'QWERTYUIOPASDFGHJKLZXCVBNM';
  con3 = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
  con4 = '!@#$%^&*()_+|\=-<>.,/?''; :"][}{';
  con5 = 'йцукенгшщзхъфывапролджэячсмитьбю';
  con6 = 'ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ';
  con7 = 'йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ';
var
  s: string;
  r, m, k, l: Integer;
begin
  Randomize;
  if Edit1.text <> '' then
    kol := StrToInt(Edit1.Text)
  else
  begin
    goto 1;
  end;
  begin
    Edit2.Text := 'Введите значение...';
  end;
  Edit3.Clear;
  Status.SimpleText := 'Подождите, пароль генерируется...';
  repeat
    r := Random(8)+1;
    if kol > 0 then
      if c1.Checked or c2.Checked or c3.Checked or c4.Checked then
        case r of
          1: if c2.Checked and ra1.Checked then
               s := s + con1[Random(Lenght(con1)-1)+1];
          2: if c2.Checked and ra2.Checked then
               s := s + con2[Random(Lenght(con2)-1)+1];
          3: if c2.Checked and ra3.Checked then
               s := s + con3[Random(Lenght(con3)-1)+1];

          4: if c4.Checked then
               s := s + con4[Random(Lenght(con4)-1)+1];
          5: if c1.Checked then
               s := s + IntToStr(Random(10));

          6: if c3.Checked and ra1.Checked then
               s := s + con5[Random(Lenght(con5)-1)+1];
          7: if c3.Checked and ra2.Checked then
               s := s + con6[Random(Lenght(con6)-1)+1];
          8: if c3.Checked and ra3.Checked then
              s := s + con7[Random(Lenght(con7)-1)+1];
        end
    else
    begin
      s := 'Выберите символы которые вы хотите использовать';
      kol := Length(s);
    end;
  until Length(s) >= kol;
  while Length(s) > kol do
    Delete(s, 1, 1);

  1:
  if Edit1.Text = '' then
  begin
    s := 'Выберите кол-во символов в пароле!';
    kol := Length(s);
    Status.SimpleText := 'Выберите кол-во символов в пароле!';
    Edit2.Text := s;
    Edit3.Text := 'Выберите кол-во символов в пароле!';
  end
  else
  begin
    Edit2.Text := s;
    for m := 1 to kol do
      Edit3.Text := Edit3.Text + ' ' + s[m];
    Status.SimpleText := 'Пароль готов!';
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit2.Clear;
  Edit3.Clear;
  Edit2.Text := 'Здесь будет пароль!';
  u1.Position := 8;
  Edit3.Text := 'А здесь каждый символ отдельно!';
  kol := 0;
end;

procedure TForm1.N101Click(Sender: TObject);
begin
  u1.Position := u1.Position + 10;
end;

procedure TForm1.N102Click(Sender: TObject);
begin
  if u1.Position > 10 then
    u1.Position := u1.Position - 10
  else
    Status.SimpleText := 'Слишком маленькое значение!!!';
end;

procedure TForm1.SpinKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if (key = 13) then GenClick(gen) ;
end;

procedure TForm1.edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (key in ['0'..'9']) then key := #0;
end;

end.


Source: http://delphiworld.narod.ru/
ID: 04034



Случайные символы из таблицы[править | править код]

Вам понадобилось, чтобы Ваше приложение само создавало пароли? Возможно данный способ Вам пригодится. Всё очень просто: пароль создаётся из символов, выбираемых случайным образом из таблицы.

Пароль создаётся из символов, содержащихся в таблице.

Внимание
Длина пароля должна быть меньше, чем длина таблицы!


Запускаем генератор случайных чисел (только при старте приложения).

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
end;


Описываем функцию:

function RandomPwd(PWLen: integer): string;
// таблица символов, используемых в пароле
const StrTable: string =
  '!#$%&/()=?@<>|{[]}\*~+#;:.-_' +
  'ABCDEFGHIJKLMabcdefghijklm' +
  '0123456789' +
  'ДЦЬдцьЯ' +
  'NOPQRSTUVWXYZnopqrstuvwxyz';
var
  N, K, X, Y: Integer;
begin
  // проверяем максимальную длину пароля
  if (PWlen > Length(StrTable)) then
    K := Length(StrTable)-1
  else
    K := PWLen;
  SetLength(Result, K);              // устанавливаем длину конечной строки
  Y := Length(StrTable);             // Длина Таблицы для внутреннего цикла
  N := 0;                            // начальное значение цикла

  while N < K do                     // цикл для создания K символов
  begin
    X := Random(Y) + 1;              // берём следующий случайный символ
    // проверяем присутствие этого символа в конечной строке
    if (Pos(StrTable[X], Result) = 0) then
    begin
      Inc(N);                        // символ не найден
      Result[N] := StrTable[X];      // теперь его сохраняем
    end;
  end;
end;


Ну и обработчик нажатия кнопки будет выглядеть так:

procedure TForm1.Button1Click(Sender: TObject);
var
  cPwd: string;
begin
  // вызываем функцию генерации пароля из 30 символов
  cPwd := RandomPwd(30);
  // ...
end;


Source: http://delphiworld.narod.ru/
ID: 04035



Случайные пароли с точки зрения математики[править | править код]

Тут поговорим случайных паролях с точки зрения математики. Конкретнее - как количество возможных вариантов пароля зависит от его длины и размерности используемого при генерации "алфавита". Тема не новая, но ни в одной статье на эту тему (во всяком случае из тех, что я читал) вопрос не рассматривается достаточно подробно. Частенько просто отделываются утверждением, что возможных вариантов паролей "огромное количество". Но это понятие растяжимое - современный ПК тоже выполняет "огромное количество" операций в секунду. Так сколько ему понадобится времени, чтобы при переборе вариантов добраться до нашего пароля? Особо продвинутые авторы пугают читателя огромными числами. Не будем верить на слово - если мы пишем программу, в которой предусмотрены пароли, надо самим уметь оценить их надежность. Не вдаваясь в строгое математическое доказательство, посмотрим, откуда берутся эти зверские числа и как их рассчитать для каждого конкретного случая.

Давайте договоримся, что мы имеем алфавит из n возможных символов, а наш пароль k символов в длину. Надо узнать, сколько вариантов пароля может быть в принципе, и дополнительно посмотрим, сколько будет вариантов паролей из неповторяющихся символов - иногда встречаются утверждения, что такой пароль лучше. Не ручаюсь за точность терминологии, лень было искать:), просто для себя назовем такие пароли соответственно "обычными" и "уникальными".

Обычные пароли[править | править код]

Как мы только что договорились, обычными называем пароли, которые могут содержать повторяющиеся символы. То есть это полное количество комбинаций длиной k, которые мы можем составить из n элементов. Слишком сильно в математику вдаваться не будем, а рассмотрим несколько простых примеров. Начнем как положено, с самого начала.

Пример 1: У нас есть элементы "А" и "В". Сколько комбинаций длиной 1 можно из них сотворить? Очевидно, две. Попутно отмечаем на будущее, что это равно nk.

Пример 2: У нас есть элементы "А", "В" и "С". Сколько имеем комбинаций длиной в 2 символа? Давайте считать. Перебираем по принципу "каждый с каждым". Получаем "АА", "АВ", "АС", "ВА", "ВВ", "ВС", "СА", "СВ", "СС", всего 9. Занятное совпадение - снова nk :)

Дальше предлагаю просто принять на веру, что их nk, поскольку так оно и есть, строго доказывать будет длинновато. Интересующиеся могут обратиться к разделу алгебры "Комбинаторика". Это называется размещения с повторениями. Рассмотрим более практический пример. Число букв английского алфавита 26. Составляем всевозможные пароли длиной в 9 символов. Их у нас 269=5 429 503 678 976 штук. Для начала неплохо:)

Уникальные пароли[править | править код]

Снова вернемся к примерам. Уникальные пароли не содержат повторяющихся символов, потому первый пример оставляет нам оба варианта. Из второго примера мы должны вычеркнуть "АА", "ВВ" и "СС", то есть имеем шесть случаев. В математике это называется размещениями. Количество размещений (без повторения) рассчитываем по формуле n*(n-1)*(n-2)*...*(n-k+1) = n! / (n-k)! (что такое факториал, надеюсь, все помнят). Сразу видим, что для наших примеров получаем соответственно 2 и 6, то есть все правильно. Снова тот же более практический пример - на этот раз имеем 26! / (26 - 9)! = 26! / 17! = 1 133 836 704 000 вариантов. Даже без "куркулятора" понятно, насколько мы сузили диапазон возможных паролей наложением условия неповторяемости символов. Это к вопросу об использовании "уникальных" паролей:)

Реальный пример[править | править код]

Давайте перейдем к практическим вещам. Например, рассмотрим пароли MS Office. Они могут быть до 15 знаков в длину, включать буквы (не только английские, но и языков локализации), цифры, а также специальные символы ("{", "#", "!" и т.п.). Кроме того, учитывается регистр символов, то есть английских букв реально можем использовать 52. Надо отметить, что MS Office ничего не имеет против пароля, состоящего из букв разных языков, но я бы не стал такого делать - легко самому запутаться. Потому прикидываем для английского - 52 буквы, 10 цифр, еще пару десятков надо накинуть на спецсимволы... Для круглого счета определим наш алфавит в 80 символов. Максимальное количество паролей максимальной длины при таком допущении будет примерно 3,5 * 1028. А если не допускать повторения символов? 8,6 * 1027. Снова вариантов в несколько раз меньше.

Зависимости[править | править код]

Попробуем ответить на самый интересный вопрос - как количество вариантов зависит от размерности алфавита и длины пароля? И что вообще важнее - увеличивать размерность алфавита или использовать пароль максимальной длины? Формулы этих зависимостей мы уже получили, для наглядности теперь нарисуем пару картинок. Снова берем 80 символов алфавита и 15 символов пароля.

Clip0102.png

Рисунок 1: Зависимость количества "обычных" вариантов от размерности алфавита и длины пароля.


К сожалению, "рисовалка" немного не дотягивает до максимальных значений, но все закономерности налицо. На мой взгляд, рисунки показывают, что минимально приемлемый пароль имеет от 10 символов в длину и от 25 символов использованного алфавита, и что количество вариантов сильнее зависит от размерности алфавита.

Так сколько же компьютеру понадобится времени для взлома нашего документа? Давайте оценим. Специально заходил на сайты нескольких утилит для "восстановления забытых паролей", но сведений о скорости перебора там благоразумно не приводилось:) Единственное, что удалось откопать в сети - упоминание о том, что одна из таких программ, написанная несколько лет назад, перебирает 85000 вариантов в секунду на Pentium III. В алгоритмах с тех пор вряд ли что-то существенно изменилось. Давайте введем поправку на возросшие компьютерные мощности, например, помножим на пять. Для 9-ти значного пароля и для алфавита в 26 символов получится около 145 суток. Это для обычных паролей. Для паролей из неповторяющихся символов получается ровно месяц. Конечно, эти рассуждения относятся к взлому пароля прямым перебором вариантов - относительно иных способов не берусь подсчитать.


Author: Archer
Source: http://delphiworld.narod.ru/
ID: 04036