Безопасность Post-It

16

Как вы, наверное, знаете, хакеры есть везде, и они хотят взломать все. Вас попросили сделать требования паролю, которые остановят любого хакера . Проблема в том, что ваш начальник слышал, что платить за LOC - это зло, и он платит вам $ 1800 - $ 0,03 * символов, вставляемых в месяц, чтобы вы написали простейшую вещь, которая могла бы сработать. Таким образом, вы должны использовать небольшое количество символов (надеюсь, очень маленькие), или иначе забыть о деньгах. Кроме того, вашему боссу все равно, на каком языке вы будете пользоваться.

Требования к надежным паролям аналогичны требованиям в упомянутой статье, за исключением того, что требования на основе словаря были удалены, чтобы избежать зависимости решения от внешних файлов, вам не нужно проверять перестановку букв (трудно понять, что это на самом деле означает), последнее правило удалено (что такое 3/4?) и оно не проверяет старые пароли.

Точные требования после удаления определенных требований из связанной статьи:

  • иметь не менее 8 символов!
  • не длиннее 12 символов!
  • иметь заглавные и строчные буквы!
  • не более 8 заглавных букв!
  • иметь не более 8 строчных букв!
  • иметь как минимум 2 буквы!
  • есть ведущее письмо!
  • иметь как минимум 1 цифру (ы)!
  • не быть вашим именем пользователя!
  • не быть вашим именем пользователя задом наперед!
  • не содержать ваше имя пользователя!
  • не содержать ваше имя пользователя в обратном направлении!
  • иметь не более 1 пары повторяющихся символов!
  • не имеют 3 вхождений одного и того же персонажа!
  • не содержит карат (^)
  • не содержит места
  • не содержит =
  • не conatain &
  • не содержит #
  • не содержать,
  • не согласен ;
  • не содержат "
  • не содержит>
  • не содержит <
  • не содержит [
  • не содержат |
  • не содержать)

Все орфографические ошибки в этом списке остались без изменений.

$ ./checkpass
Username: John
Password: L!]E2m69
OK.

$ ./checkpass
Username: John
Password: JohnnhoJ12
Nope.

$ ./checkpass
Username: JOE.smith
Password: JOE!smith123
OK.

Самый короткий код выигрывает деньги (отправляется в виде файла JPG). Он должен отображать приглашения «Имя пользователя» и «Пароль:» и отвечать точным сообщением.

Конрад Боровски
источник
1
Приятно видеть кодовую игру в гольф в статье Daily WTF, +1 ;-)
ChristopheD
1
Первый пример должен потерпеть неудачу («иметь прописные и строчные буквы!»), Не так ли?
Говард
@Howard: это означает, что в пароле нужны прописные и строчные буквы. Обратите внимание на отсутствие слова «не».
Конрад Боровски
В некоторых шрифтах не очень очевидно, что буква l в этом первом пароле - это строчная буква, а не цифра номер один, поэтому я редактирую, чтобы заменить ее на однозначную строчную букву.
Питер Тейлор
@PeterTaylor Ах, спасибо. На самом деле я читаю это как 1(цифра один) вместо ell.
Говард

Ответы:

8

Perl, 203 194 189 193 символов

Вот мой Perl берет на себя проблему:

print"Username: ";chop($u=<>);$n=reverse$u;print"Password: ";$_=<>;
say/^\pL.{7,11}$/*/\d/*/[A-Z]/*9>y/A-Z//&y/a-z//<9*/[a-z]/*
!/[" #,;->^&[|)]|(.)(.*\1.*\1|\1.*(.)\3)|\Q$u\E|\Q$n/?"OK.":"Nope."

Регулярные выражения проверяют, чтобы пароль:

  • начинается с буквы, имеет от восьми до двенадцати символов

  • содержит цифру

  • содержит заглавную букву

  • имеет восемь или меньше заглавных букв

  • имеет восемь или меньше строчных букв

  • содержит строчную букву

  • не содержит ни одного из запрещенных знаков препинания, трех вхождений любого символа, более одного вхождения двойного символа, имени пользователя или обратного имени пользователя.

(Спасибо Питеру Тейлору за то, что он указал на ошибку в версии с 189 символами.)

Хлебница
источник
Выяснили, как запустить это на ideone с помощью теста, use v5.10;и он не прошел мой тестовый сценарий "Правильно ли заданы регулярные выражения". См. Ideone.com/QKFnZ
Питер Тейлор,
@PeterTaylor: я не знаю о Ruby, но в Perl исправление будет \Q$u\E|\Q$n(последнее \Eможно пропустить, если эта часть будет перемещена в конец).
Конрад Боровски
OTOH Я думаю, что один символ может быть сохранен путем объединения повторов как (.)(.*\1.*\1|\1.*(.)\3)(не проверено - я не собираюсь пытаться написать сценарий полного теста батареи с ideone).
Питер Тейлор
5

Рубин, 270 знаков

$><<"Username: ";u=gets.chop
$><<"Password: ";gets
puts ('^.{8,12}$+\p{Lower}+\p{Upper}+^(\p{Alpha}.*){2}+\d+(\p{Lower}.*){9}+(\p{Upper}.*){9}+(.)\1.*(.)\2+(.).*\1.*\1+[ ^=&#,;"<>\[|)]+'+u+?++u.reverse).split(?+).map{|r|/#{r}/=~$_??A:?B}*""=="AAAAABBBBBBB"?"OK.":"Nope."

Реализация ruby ​​основана на двенадцати регулярных выражениях. Каждое выражение является либо положительным совпадением (первые пять), либо отрицательным (последние семь). В качестве ограничения имя пользователя может содержать только буквы или цифры.

Положительные совпадения регулярного выражения:

  • /^.{8,12}$/: иметь не менее 8 символов! не длиннее 12 символов!
  • /\p{Lower}/и /\p{Upper}/: иметь заглавные и строчные буквы!
  • /^(\p{Alpha}.*){2}/: иметь по крайней мере 2 буквы, иметь начальную букву!
  • /\d/: иметь хотя бы 1 цифру (ы)!

Отрицательные совпадения с регулярным выражением:

  • /(\p{Lower}.*){9}/: иметь не более 8 строчных букв!
  • /(\p{Upper}.*){9}/: иметь не более 8 заглавных букв!
  • /(.)\1.*(.)\2/: иметь не более 1 пары повторяющихся символов!
  • /(.).*\1.*\1/: не иметь 3 вхождения одного и того же персонажа!
  • /[ ^=&#,;"<>\[|)]/: не содержит каретки, пробела, =, &, #, ,,;, ",>, <, [, |,)
  • /#{u}/: не быть вашим именем пользователя! не содержать ваше имя пользователя!
  • /#{u.reverse}/: не быть вашим именем пользователя в обратном направлении !, не содержать ваше имя в обратном направлении!
Говард
источник
Это не исключает имени пользователя, поэтому совершенно действительный пароль может быть отклонен. Тестовый пример на ideone.com/bPpeo
Питер Тейлор,
@PeterTaylor Вот почему я отметил ограничение для имен пользователей в своем ответе.
Говард
1

Python 3, 291 байт / символы

from re import*
n,p=map(input,["Username: ","Password: "])
c,U,L=lambda x:len(split("[%s]"%x,p)),"A-Z","a-z"
print(["OK.","Nope."][any([8>len(p)>12,2>c(U)>9,2>c(L)>9,3>c(U+L),match(U+L,p),2>c("0-9"),n in p,n[::-1]in p,any(c(x)>3 for x in p),len(findall("(.)\\1",p))>1,c(' ^=&#,;"><[|)')>1])])

Более красиво отформатирован и прокомментирован:

# import all elements from the regular expression module
from re import *

# Get the two lines of user input (username `n`, password `p`):
n, p = map(input, ["Username: ","Password: "])

# Assign some internally useful shortcuts (uppercase letters `U`, lowercase letters `L`):
# `c(x)` counts the occurrences of pattern `x` in the password `p` plus 1
c, U, L = lambda x: len(split("[%s]" % x, p)), "A-Z", "a-z"

# Print the test result: `"OK."` if the `any(...)` function returned `False`, else `"Nope."`.
# The `any(...)` combines the result of all enclosed checks and returns `True` if at least
# one of the checks failed (returned `True`).
print(["OK.", "Nope."][any([                                # vvv--- CHECKS: ---vvv
                             8>len(p)>12,                   # password length 8-12
                             2>c(U)>9,                      # 1-8 uppercase letters
                             2>c(L)>9,                      # 1-8 lowercase letters
                             3>c(U+L),                      # at least 2 letters
                             match(U+L,p),                  # starts with a letter
                             2>c("0-9"),                    # at least 1 digit
                             n in p,                        # username is not (in) the pw.
                             n[::-1]in p,                   # reversed name not (in) the pw.
                             any(c(x)>3 for x in p),        # at most 3 same characters
                             len(findall("(.)\\1",p))>1,    # at most 1 pair (e.g. "AA")
                             c(' ^=&#,;"><[|)')>1])         # does not contain special char.
                           ])

Вы можете найти это решение на ideone.com , но вывод выглядит немного уродливо, потому что он не показывает предопределенный ввод или даже разрывы строк. Также комбинация логин-пароль "JOE.smith"- "JOE!smith123"в данный момент вводится как фиксированные входные данные.
Я добавил разбивку всех проверок в качестве отладочного вывода, хотя.

Byte Commander
источник