Seguridad por post-it

16

Como ya sabrás, los hackers están en todas partes y quieren hackear todo. Se le pidió que establezca requisitos de contraseña que detendrán a cualquier hacker . El problema es que su jefe ha escuchado que pagar por LOC es malo y le paga $ 1800 - $ 0.03 * caracteres insertados por mes para que escriba lo más simple que posiblemente podría funcionar. Por lo tanto, debe usar una pequeña cantidad de caracteres (con suerte muy pequeños), o de lo contrario olvidarse del efectivo. Además, a tu jefe no le importa qué idioma usarás.

Los requisitos para contraseñas buenas son similares a los del artículo mencionado, excepto que los requisitos basados ​​en el diccionario se eliminaron para evitar que la solución dependa de archivos externos, no es necesario verificar si las letras se reorganizan (difícil de entender lo que realmente significa), se elimina la última regla (¿Qué es 3/4?) y no verifica las contraseñas antiguas.

Los requisitos exactos después de eliminar ciertos requisitos del artículo vinculado son:

  • tener al menos 8 caracteres!
  • ¡No tenga más de 12 caracteres!
  • tener mayúsculas y minúsculas!
  • ¡no tenga más de 8 letras mayúsculas!
  • ¡no tenga más de 8 letras minúsculas!
  • tener al menos 2 letra (s)!
  • ¡Ten una carta principal!
  • tener al menos 1 dígito (s)!
  • ¡no seas tu nombre de usuario!
  • ¡No seas tu nombre de usuario al revés!
  • No contiene su nombre de usuario!
  • ¡No contenga su nombre de usuario al revés!
  • ¡No tenga más de 1 par (es) de caracteres repetidos!
  • ¡No tiene 3 ocurrencias del mismo personaje!
  • no contiene quilates (^)
  • no contiene espacio
  • no contiene =
  • no conatain &
  • no contienen #
  • no contienen ,
  • no conatain ;
  • no contienen "
  • no contiene>
  • no contiene <
  • no contienen [
  • no contiene |
  • no contienen )

Todos los errores ortográficos en esta lista se dejaron como están.

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

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

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

El código más corto gana dinero (enviado como archivo JPG). Tiene que mostrar las indicaciones "Nombre de usuario:" y "Contraseña:" y responder con el mensaje exacto.

Konrad Borowski
fuente
1
Agradable, ver un desafío de código de golf en un artículo de Daily WTF, +1 ;-)
ChristopheD
1
El primer ejemplo debería fallar ("tiene mayúsculas y minúsculas"), ¿no?
Howard
@Howard: significa que se necesitan letras mayúsculas y minúsculas en la contraseña. Observe la falta de la palabra "no".
Konrad Borowski
No es muy obvio en algunas fuentes que l en esa primera contraseña sea un ell en minúscula y no el número uno, así que estoy editando para reemplazarlo con una letra minúscula inequívoca.
Peter Taylor
@PeterTaylor Ah, gracias. De hecho, lo leí como 1(dígito uno) en lugar de ell.
Howard

Respuestas:

8

Perl, 203 194 189 193 caracteres

Aquí está mi versión de Perl sobre el 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."

Las expresiones regulares verifican, en orden, que la contraseña:

  • comienza con una letra, tiene de ocho a doce caracteres

  • contiene un dígito

  • contiene una letra mayúscula

  • tiene ocho o menos letras mayúsculas

  • tiene ocho o menos letras minúsculas

  • contiene una letra minúscula

  • no contiene ninguno de los signos de puntuación prohibidos, tres ocurrencias de cualquier carácter, más de una aparición de un carácter duplicado, el nombre de usuario o el nombre de usuario invertido.

(Gracias a Peter Taylor por señalar un error en la versión de 189 caracteres).

caja de pan
fuente
Descubrí cómo ejecutar esto en ideone con use v5.10;y falla mi caso de prueba "se regexes escaparon correctamente". Ver ideone.com/QKFnZ
Peter Taylor
@PeterTaylor: No sé acerca de Ruby, pero en Perl la solución sería \Q$u\E|\Q$n(la última \Ese puede omitir, si esta parte se moviera para finalizar).
Konrad Borowski
OTOH Creo que un personaje se puede guardar combinando las repeticiones como (.)(.*\1.*\1|\1.*(.)\3)(no probado, no voy a intentar crear una batería de prueba completa con ideone).
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."

Una implementación de ruby ​​basada en doce expresiones regulares. Cada expresión es una coincidencia positiva (primeros cinco) o negativa (últimos siete). Como restricción, el nombre de usuario solo puede contener letras o dígitos.

La expresión regular positiva coincide:

  • /^.{8,12}$/: ¡tenga al menos 8 caracteres! ¡No debe tener más de 12 caracteres!
  • /\p{Lower}/y /\p{Upper}/: tener mayúsculas y minúsculas!
  • /^(\p{Alpha}.*){2}/: ¡tenga al menos 2 letra (s) !, tenga una letra inicial!
  • /\d/: tener al menos 1 dígito (s)!

La expresión regular negativa coincide:

  • /(\p{Lower}.*){9}/: ¡no tenga más de 8 letras minúsculas!
  • /(\p{Upper}.*){9}/: ¡no tenga más de 8 letras mayúsculas!
  • /(.)\1.*(.)\2/: ¡no tenga más de 1 par (es) de caracteres repetidos!
  • /(.).*\1.*\1/: no tiene 3 ocurrencias del mismo personaje!
  • /[ ^=&#,;"<>\[|)]/: no contiene cursor, espacio, =, &, #, ,,;, ",>, <, [, |,)
  • /#{u}/: ¡no sea su nombre de usuario !, ¡no contenga su nombre de usuario!
  • /#{u.reverse}/: ¡no sea su nombre de usuario al revés !, ¡no contenga su nombre de usuario al revés!
Howard
fuente
Esto no escapa al nombre de usuario, por lo que se puede rechazar una contraseña perfectamente válida. Caso de prueba en ideone.com/bPpeo
Peter Taylor
@PeterTaylor Es por eso que noté la restricción para los nombres de usuario en mi respuesta.
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])])

Más bien formateado y 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.
                           ])

Puede encontrar esta solución en ideone.com , pero el resultado se ve un poco feo porque no muestra la entrada predefinida o incluso los saltos de línea allí. Además, la combinación de nombre de usuario-contraseña "JOE.smith"- "JOE!smith123"se introduce en la actualidad como datos de entrada fijos.
Sin embargo, agregué un desglose de todos los controles como salida de depuración.

Byte Commander
fuente