포스트잇에 의한 보안


16

아시다시피 해커는 어디에나 있으며 모든 것을 해킹하려고합니다. 해커를 막을 수있는 암호를 요구했습니다 . 문제는 상사가 LOC 비용을 지불하는 것이 악하다고 들었고 월간 삽입 한 문자 $ 1800-$ 0.03 *를 지불하면 가장 간단한 것을 쓸 수있게됩니다. 따라서 적은 수의 문자를 사용하거나 (아주 매우 작은) 현금을 잊어야합니다. 또한 상사는 어떤 언어를 사용할지 신경 쓰지 않습니다.

올바른 암호에 대한 요구 사항은 외부 파일에 따라 솔루션이 종속되지 않도록 사전 기반 요구 사항이 제거되었다는 점을 제외하고는 언급 된 기사의 요구 사항과 유사합니다. 문자가 재정렬되는 것을 확인할 필요가 없습니다 (실제 의미를 이해하기 어렵다). 마지막 규칙이 제거되고 (3/4 란?) 이전 비밀번호는 확인하지 않습니다.

링크 된 기사에서 특정 요구 사항을 제거한 후의 정확한 요구 사항은 다음과 같습니다.

  • 8 자 이상이어야합니다!
  • 12 자 이하 여야합니다!
  • 대문자와 소문자가 있습니다!
  • 대문자 8자를 넘지 않아야합니다!
  • 소문자는 8 자 이하 여야합니다!
  • 최소한 2 글자가 있습니다!
  • 선행 편지가 있습니다!
  • 1 자리 이상이어야합니다!
  • 귀하의 사용자 이름이 아닙니다!
  • 사용자 이름이 거꾸로되지 마십시오!
  • 사용자 이름을 포함하지 마십시오!
  • 사용자 이름을 거꾸로 포함하지 마십시오!
  • 한 쌍의 반복되는 문자를 초과하지 않아야합니다!
  • 아니 3 개가 발행 수 와 동일한 문자를!
  • 캐럿을 포함하지 않음 (^)
  • 공간이 없습니다
  • 포함하지 =
  • 하지 conatain &
  • #을 포함하지 않음
  • 포함하지 않음
  • conatain 하지 ;
  • "를 포함하지 않음
  • 포함하지>
  • 포함하지 <
  • 포함하지 않음 [
  • 포함하지 |
  • 포함하지 않음)

이 목록의 모든 맞춤법 오류는 그대로 남아 있습니다.

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

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

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

가장 짧은 코드는 돈을 이깁니다 (JPG 파일로 전송). "Username :"및 "Password :"프롬프트를 표시하고 정확한 메시지로 회신해야합니다.


1
니스, Daily WTF 기사에서 코드 골프 도전 과제보기, +1 ;-)
ChristopheD

1
첫 번째 예제는 실패해야합니다 ( "대문자가 소문자로되어 있습니다!").
Howard

@Howard : 암호에 대문자와 소문자가 모두 필요하다는 것을 의미합니다. 단어 "not"이 없다는 것을 주목하십시오.
Konrad Borowski 2016 년

일부 글꼴에서는 첫 번째 암호의 l이 소문자이며 숫자가 아니라는 것이 분명하지 않으므로 모호하지 않은 소문자로 바꾸도록 편집하고 있습니다.
피터 테일러

@PeterTaylor 아, 감사합니다. 실제로 나는 그것을 1ell 대신 (숫자 1) 로 읽습니다 .
Howard

답변:


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."

정규식은 순서대로 암호를 확인합니다.

  • 문자로 시작하고 8 ~ 12 자

  • 숫자를 포함

  • 대문자를 포함합니다

  • 대문자가 8 자 이하

  • 소문자 8 자 이하

  • 소문자를 포함합니다

  • 금지 된 문장 부호, 문자의 세 가지 발생, 두 배의 문자 발생, 사용자 이름 또는 사용자 이름이 반전 된 문자를 포함하지 않습니다.

(189-char 버전의 버그를 지적한 Peter Taylor에게 감사합니다.)


ideone에서 이것을 실행하는 방법을 알아 냈는데 use v5.10;" 정규가 제대로 이스케이프 되었습니까? "테스트 사례에 실패했습니다. ideone.com/QKFnZ
Peter Taylor

@PeterTaylor : Ruby에 대해서는 잘 모르지만 Perl에서는 수정 될 것입니다 \Q$u\E|\Q$n( \E이 부분이 끝날 경우 마지막 부분은 건너 뛸 수 있습니다).
Konrad Borowski 2016 년

OTOH (.)(.*\1.*\1|\1.*(.)\3)반복문을 다음과 같이 병합하여 한 문자를 절약 할 수 있다고 생각합니다 (테스트되지 않음-전체 테스트 배터리를 이데온으로 스크립팅하지는 않습니다).
피터 테일러

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."

루비 구현은 12 개의 정규 표현식을 기반으로합니다. 각 표현은 긍정적 인 일치 (처음 5 개)이거나 부정적인 것 (후기 7 개)입니다. 제한적으로 사용자 이름에는 문자 나 숫자 만 포함될 수 있습니다.

긍정적 인 정규식 일치 :

  • /^.{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/: 같은 등장 인물이 3 가지 없습니다!
  • /[ ^=&#,;"<>\[|)]/: 캐럿, 공백, =, &, #, ,,;, ",>, <, [, |,)를 포함하지 않음
  • /#{u}/: 사용자 이름이 아닙니다! 사용자 이름을 포함하지 마십시오!
  • /#{u.reverse}/: 사용자 이름이 거꾸로되어 있지 않아야합니다!

이것은 사용자 이름을 이탈하지 않으므로 완벽하게 유효한 암호를 거부 할 수 있습니다. ideone.com/bPpeo의
Peter Taylor

@PeterTaylor 그렇기 때문에 답변에 사용자 이름에 대한 제한 사항이 언급되었습니다.
Howard

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"현재 고정 된 입력 데이터로서 입력된다.
그래도 모든 검사에 대한 분석을 디버그 출력으로 추가했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.