Усовершенствование формы ввода пароля "Log in Dialog".
Автор 14.09.2006 11:34:58   
03.03.2003 г.
С подвигнутые естественным желанием ограничить несанкционированный доступ к своему творению, программисты, творящие на Visual Basic , часто используют форму "Log in Dialog". Как известно, все формы, добавляемые из заготовок в меню "Проект"-> "Добавить форму" являются "полуфабрикатами", и как их кулинарные аналоги, конечно, можно употреблять в том виде "как есть", но это будет или не вкусно или для желудка вредно, хотя наверняка не смертельно. В общем, из полуфабриката "Log in Dialog" можно приготовить хорошее блюдо, причем с минимальными затратами совершенствование формы ввода пароля "Log in Dialog".

С подвигнутые естественным желанием ограничить несанкционированный доступ к своему творению, программисты, творящие на Visual Basic , часто используют форму "Log in Dialog". Как известно, все формы, добавляемые из заготовок в меню "Проект"-> "Добавить форму" являются "полуфабрикатами", и как их кулинарные аналоги, конечно, можно употреблять в том виде "как есть", но это будет или не вкусно или для желудка вредно, хотя наверняка не смертельно. В общем, из полуфабриката "Log in Dialog" можно приготовить хорошее блюдо, причем с минимальными затратами.
Прежде всего, на мой взгляд, основным недостатком формы "Log in Dialog" является то, что ни как не скрывает пароль от постороннего взгляда. Я хочу сказать, что в откомпилированной программе ваше секретное слово лежит на самом видном месте, и его можно видеть перед надписью "Invalid Password, try again!". Единственное, что с ним произошло после компиляции - все буквы в слове написаны через интервал, по крайней мере, так пароль отображается в Блокноте. Поверьте, читабельность от этого не уменьшилась. Следующий недостаток - ни как не используется поле "User Name:", а как там у Станиславского: " Если на сцене висит ружье, то оно должно выстрелить". Так вот - не стреляет пока. Из первого недостатка вытекает второй - пароль жестко задан в процессе создания программы, и ни какой возможности заменить его нет, пусть даже весь мир его уже знает. А что бы была возможность пароль периодически менять, его удобнее хранить где то во внешнем файле, (по типу файлов .pwl в Windows системе), а при нынешнем положении дел хранить пароль в открытом виде равносильно тому, что не иметь его вовсе.
Из вышесказанного следует, что пароль надо шифровать, шифровать и еще раз шифровать. Я не крупный специалист в области криптографии, но простенький шифрующий код написать не представляет труда. И что самое приятное, можно запутать свой пароль как угодно, хоть с помощью крипта алгоритма повышенной секретности ( 128-bit keys ) и не задумываться о расшифровывающем алгоритме - он нам не нужен. Такой код шифра я вам не покажу, но приведу пример, достаточно эффективного кода средней секретности (уровень "ДСП").
Начнем с начала. Создаем стандартный exe проект. Добавляем заготовку в меню "Проект"-> "Добавить форму" -> "Log in Dialog". На эту форму положите еще один TextBox, он пригодиться для предварительной подготовки. Не надо его переименовывать, пусть будет Text1, все равно его потом удалим. Откроем код кнопки cmdOK. Вот здесь внесем небольшие изменения. В начале несколько слов о алгоритме шифрования. В поле "Password:" вноситься пароль не менее 3 знаков. Знаки могут быть любые, отображаемые, с кодами 1 - 255. На первом этапе все знаки будут перетасованы. Для этого переменная i будет пробегать по длине текста несколько раз например 4. Эта цифра может, как вы поняли, меняться в конкретном алгоритме, меняя так называемый ключ шифра. Вырезая первый символ и меняя его с группой символов, имеющих номера больше S получим перетасовку текста. Значение переменной S будем вычислять исходя из числа Asc(P), так чтобы S не превосходило длины текста:
For i = 1 To 4 * L
P = Mid$(Passw, 1, 1)
S = Asc(P$) - (L - 2) * Int(Asc(P$) / (L - 2)) + 2
Passw = Mid$(Passw, S + 1) + Mid$(Passw, 2, S - 1) + P$
Next i
Т.о. если в поле Password ввести слово "пароль" т.е. Passw = пароль, то после преобразования получим что то вроде "оарьлп". Теперь можно приступать ко второму этапу шифрования. На этом этапе зашифруем полученное слово методом посимвольного наложения. Значение переменной i будет пробегать по длине текста и заменять i-й символ на символ с номером, смещенным на S. Значение смещения у нас в целях криптостойкости будет не постоянным, а изменяться в зависимости от номера i-го символа. Вот что получится:

For i = 1 To L
' Смещаем код i символа на величину S, которая зависит от самого символа
S = Asc(Mid$(Passw, i, 1)) - Asc("a")
N = Asc(Mid$(Passw, i, 1)) + S
' Но N должна быть строго в пределах 1-255, что бы не вызвать ошибки,
' а так как с 1 по 31 символы отображаются однообразно, а 34 это
' знак ", который не хочет работать в строковой переменной то
' лучше начать сразу с 35 символа
If Abs(N) < 35 Then N = N + 35
If N > 255 Then N = N - 255
' Собираем зашифрованный пароль в единый кракозябл
ZasPassw = ZasPassw + Chr$(N)
Next i

В результате этих преобразований слово "пароль" превращается в симпатичное "|`?Шv~", которое гармонично вписывается в откомпилированный код, не привлекая особого внимания. Для пущей секретности рекомендуется надпись "Invalid Password, try again!" не выводить, дабы не привлекать внимания к месту хранения пароля. Ибо кто знает, тот и так все поймет. Если вы еще не запутались, то продолжим. В начале я рекомендовал нарисовать на форме еще один TextBox. Так вот он нам нужен для того, чтобы отобразить получившийся пароль в зашифрованном виде, для последующего его копирования:
Text1 = ZasPassw

А скопировать его надо в текст программы, в то место где идет проверка :
If txtPassword = "password" Then
'place code to here to pass the
'success to the calling sub
'setting a global var is the easiest
LoginSucceeded = True
Me.Hide
Только сравнивать будем не тот пароль, который вносили в txtPassword, а то, что
получается после шифрования. Строка " If txtPassword = "password" Then" должна быть переписана в вид "If ZasPassw = "|`?Шv~" Then". Помните, я говорил, что расшифровывать не придется? Так вот смысл в том, что если совпадают результаты шифрования, то однозначно совпадает и исходный пароль! Хотя теоретически возможна ситуация, когда два разных исходных слова создадут одинаковый шифр, но практически это не проще чем подобрать истинный пароль. Перед окончательной компиляцией программы нужно проверить как все работает и потом удалить поле Text1 и код с ним связанный.
Теперь, когда пароль стал нечитабельным, и внесение этого шифра в поле ввода пароля породит только новый, более запутанный шифр(к стати, вот еще один путь изменения ключа шифрования - повторить шифрование секретное число раз), появляется возможность хранить этот пароль во внешнем файле. Переменную ZasPassw можно записать в файл, и считывать при загрузке формы, а при надлежащей криптостойкости расшифровать ее будет достаточно сложно. Теперь смена пароля не вызывает трудностей даже в откомпилированной программе - надо только организовать ввод нового пароля. К примеру к стандартной форме "Log in Dialog" прибавить еще одну кнопку, что то типа <Сменить пароль>, код этой кнопки активизирует еще одну подобную форму, на которой три текстовых поля, подобных txtPassword: <Старый пароль>, <Новый пароль>, <Подтвердить новый пароль>. Вначале проверяется правильность старого пароля, при положительном результате запрашивается новый пароль, который проверяется с полем <Подтвердить новый пароль>, при совпадении шифруется и записывается в файл паролей, предварительно удалив старый шифр.
Так же можно найти применение полю "User Name:", к примеру присоединить его к паролю в самом начале шифрования : Passw = txtPassword.Text & txtUserName , или использовать его количество символов при определении сколько раз перемешивать символы в исходном тексте:
'Хорошенько перемешаем символы пароля!
For i = 1 To Len(txtUserName) * L
P = Mid$(Passw, 1, 1)
S = Asc(P$) - (L - 2) * Int(Asc(P$) / (L - 2)) + 2
Passw = Mid$(Passw, S + 1) + Mid$(Passw, 2, S - 1) + P$
Next I
В общем, есть размах для народного творчества. Если у кого есть что сказать на данную тему - милости прошу. С удовольствием обсудим криптостойкий алгоритм шифрования. Да, и помните старую истину - настоящий секрет только тот, что известен тебе одному.

Все вышеизложенное уместилось в коротком примере, который можно скачать.