Безпека Post-It


16

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

Вимоги до хороших паролів аналогічні вимогам у згаданій статті, за винятком вимог на основі словника, щоб уникнути того, щоб рішення залежало від зовнішніх файлів, вам не потрібно перевіряти, чи переставляють літери (важко зрозуміти, що це насправді означає), останнє правило видаляється (Що таке 3/4?), і воно не перевіряє старі паролі.

Точні вимоги після видалення певних вимог із пов'язаної статті:

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

Усі неправильні написання в цьому списку залишилися як є.

$ ./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

Перл, 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 char.)


З'ясував, як запустити це на 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."

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

Позитивні відповіді регулярного вираження:

  • /^.{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"наразі вводиться як фіксовані вхідні дані.
Я додав розбиття всіх перевірок як вихід налагодження.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.