Segurança por Post-It


16

Como você deve saber, os hackers estão por toda parte e querem invadir tudo. Você foi solicitado a criar requisitos de senha que impedirão qualquer hacker . O problema é que o seu chefe ouviu que pagar pelo LOC é ruim e ele paga entre US $ 1800 e US $ 0,03 * caracteres inseridos por mês para fazer você escrever a coisa mais simples possível. Portanto, você deve usar um pequeno número de caracteres (provavelmente muito pequeno) ou esquecer o dinheiro. Além disso, seu chefe não se importa com o idioma que você usará.

Os requisitos para boas senhas são semelhantes aos do artigo mencionado, exceto que os requisitos baseados em dicionário foram removidos para evitar que a solução dependa de arquivos externos, você não precisa verificar se as letras estão sendo reorganizadas (Difícil entender o que realmente significa), a última regra é removida (O que é 3/4?) e não verifica senhas antigas.

Os requisitos exatos após a remoção de determinados requisitos do artigo vinculado são:

  • tenha pelo menos 8 caracteres!
  • não deve ter mais de 12 caracteres!
  • ter caracteres maiúsculos e minúsculos!
  • não tenha mais que 8 letras maiúsculas!
  • não tenha mais que 8 letras minúsculas!
  • tenha pelo menos 2 letra (s)!
  • tenha uma letra principal!
  • tenha pelo menos 1 dígito (s)!
  • não seja seu nome de usuário!
  • não seja seu nome de usuário para trás!
  • não contém seu nome de usuário!
  • não contém seu nome de usuário para trás!
  • não tenha mais que 1 par (es) de caracteres repetidos!
  • não tem 3 ocorrências do mesmo personagem!
  • não contém quilates (^)
  • não contém espaço
  • não contém =
  • não conatain &
  • Não contém #
  • Não contém ,
  • não conatain ;
  • Não contém "
  • não contém>
  • não contém <
  • Não contém [
  • não contém |
  • Não contém )

Todos os erros ortográficos nesta lista foram deixados como estão.

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

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

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

O código mais curto ganha dinheiro (enviado como arquivo JPG). Ele deve mostrar "Nome de usuário:" e "Senha:" solicita e responde com a mensagem exata.


11
Bom, vendo um desafio de golfe código em um artigo do Daily WTF, +1 ;-)
ChristopheD

11
O primeiro exemplo deve falhar ("possui caracteres maiúsculos e minúsculos!"), Não deveria?
Howard

@ Howard: significa que são necessárias letras maiúsculas e minúsculas na senha. Observe a falta de palavra "não".
precisa

Não é muito óbvio em algumas fontes que o l na primeira senha é um ell minúsculo e não o número um, por isso estou editando para substituí-lo por uma letra minúscula inequívoca.
Peter Taylor

@ PeterTaylor Ah, obrigado. Na verdade, eu li como 1(dígito um) em vez de ell.
Howard

Respostas:


8

Perl, 203 194 189 193 caracteres

Aqui está minha opinião do Perl sobre o problema:

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

As expressões regulares verificam, em ordem, se a senha:

  • começa com uma letra, tem oito a doze caracteres

  • contém um dígito

  • contém uma letra maiúscula

  • tem oito ou menos letras maiúsculas

  • tem oito ou menos letras minúsculas

  • contém uma letra minúscula

  • não contém nenhum dos sinais de pontuação proibidos, três ocorrências de qualquer caractere, mais de uma ocorrência de um caractere duplicado, o nome de usuário ou o nome de usuário invertido.

(Agradecemos a Peter Taylor por apontar um bug na versão de 189 caracteres.)


Descobri como executar isso no ideone use v5.10;e ele falha no meu caso de teste "são regexes escaparam corretamente". Veja ideone.com/QKFnZ
Peter Taylor

@ PeterTaylor: Eu não sei sobre Ruby, mas no Perl a correção seria \Q$u\E|\Q$n(a última \Epode ser ignorada, se essa parte for movida para o final).
precisa

OTOH Acho que um personagem pode ser salvo mesclando as repetições como (.)(.*\1.*\1|\1.*(.)\3)(não testado - não vou tentar criar uma bateria de teste completa com ideona).
Peter Taylor

5

Ruby, 270 caracteres

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

Uma implementação ruby ​​baseia-se em doze expressões regulares. Cada expressão é uma correspondência positiva (cinco primeiras) ou negativa (sete últimas). Como restrição, o nome de usuário pode conter apenas letras ou dígitos.

Correspondências positivas de expressões regulares:

  • /^.{8,12}$/: tenha pelo menos 8 caracteres !, não deve ter mais de 12 caracteres!
  • /\p{Lower}/e /\p{Upper}/: possuem caracteres maiúsculos e minúsculos!
  • /^(\p{Alpha}.*){2}/: tenha pelo menos 2 letra (s) !, tenha uma letra à esquerda!
  • /\d/: tenha pelo menos 1 dígito (s)!

Correspondências de expressões regulares negativas:

  • /(\p{Lower}.*){9}/: não ter mais de 8 letras minúsculas!
  • /(\p{Upper}.*){9}/: não ter mais de 8 letras maiúsculas!
  • /(.)\1.*(.)\2/: não tenha mais que 1 par (es) de caracteres repetidos!
  • /(.).*\1.*\1/: não tem 3 ocorrências do mesmo personagem!
  • /[ ^=&#,;"<>\[|)]/: não contém circunflexo, espaço, =, &, #, ,,;, ",>, <, [, |,)
  • /#{u}/: não seja seu nome de usuário !, não contenha seu nome de usuário!
  • /#{u.reverse}/: não seja seu nome de usuário para trás !, não contenha seu nome de usuário para trás!

Isso não escapa ao nome de usuário, portanto, uma senha perfeitamente válida pode ser rejeitada. Caso de teste em ideone.com/bPpeo
Peter Taylor

@ PeterTaylor É por isso que observei a restrição para nomes de usuário na minha resposta.
Howard

1

Python 3, 291 bytes / caracteres

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])])

Mais bem formatado e comentado:

# 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.
                           ])

Você pode encontrar esta solução em ideone.com , mas a saída parece um pouco feia porque não mostra a entrada predefinida ou mesmo quebras de linha. Além disso, a combinação de nome de usuário e senha "JOE.smith"- "JOE!smith123"atualmente é inserida como dados de entrada fixos.
Eu adicionei uma repartição de todas as verificações como saída de depuração.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.