security encryption random cryptography

security - Generación de pines



encryption random (11)

Estoy buscando desarrollar un sistema en el que necesite asignar a cada usuario un código PIN único para la seguridad. El usuario solo ingresará este código PIN como un medio para identificarse. Por lo tanto, no quiero que el usuario pueda adivinar el código PIN de otro usuario. Suponiendo que el máximo de usuarios que tendré es 100000, ¿por cuánto tiempo debería ser este código pin?

por ejemplo, 1234 4532 3423

¿Debo generar este código a través de algún tipo de algoritmo? ¿O debería generarlo al azar?

Básicamente, no quiero que la gente pueda adivinar el código PIN de otras personas y debería admitir una cantidad suficiente de usuarios.

Lamento si mi pregunta suena un poco confusa pero con mucho gusto aclararía cualquier duda.

muchas gracias.

ACTUALIZAR

Después de leer todas las publicaciones a continuación, me gustaría agregar algunos detalles más.

  1. Lo que intento lograr es algo muy similar a una tarjeta rasca y gana.
  2. A un usuario se le da una tarjeta, que debe rayar para encontrar el código PIN.
  3. Ahora, usando este código pin, el usuario debe poder acceder a mi sistema.

No puedo agregar seguridad adicional (por ejemplo, nombre de usuario y contraseña), ya que impedirá que el usuario use la tarjeta rasca y gana. Quiero hacer que sea tan difícil como sea posible adivinar el código PIN dentro de las limitaciones.

gracias a todos por sus increíbles respuestas de nuevo.


¿Debo generar este código a través de algún tipo de algoritmo?

No. Será predecible.

¿O debería generarlo al azar?

Sí. Use un generador criptográfico aleatorio o deje que el usuario elija su propio PIN.

En teoría, 4 dígitos serán suficientes ya que los emisores de tarjetas ATM logran respaldar a una comunidad muy grande con eso (y obviamente, no pueden ser ni deben ser únicos). Sin embargo, en ese caso, debe limitar la cantidad de intentos de ingresar el PIN y bloquearlos después de tantos intentos como hacen los bancos. Y también debe hacer que el usuario proporcione una identificación de usuario (en la caja del cajero automático, eso está efectivamente en la tarjeta).

Si no quiere limitarlos de esa manera, puede ser mejor deshacerse de la idea del PIN y usar una contraseña estándar (que es esencialmente lo que es su PIN, solo que con una longitud muy corta y un juego de caracteres limitado). Si absolutamente debe restringirlo a los números (porque tiene un panel de PIN o algo así), entonces considere hacer 4 una longitud mínima (configurable) en lugar de la longitud fija.

No debe almacenar el PIN en un lugar despejado (por ejemplo, sal y hash como una contraseña), sin embargo, dada la corta longitud y el conjunto de caracteres limitado, siempre será vulnerable a una búsqueda de fuerza bruta, ya que es una forma fácil de verificarlo .

Existen otros varios esquemas que se pueden usar también, si puede decirnos más sobre sus requisitos (¿es una aplicación web? ¿Un sistema integrado ?, etc.).


¿Puedo sugerir un enfoque alternativo? Eche un vistazo a Perfect Paper Passwords , y los derivados que provocó.

Puede usar esto "tal cual" para generar PIN únicos, o simplemente para generar un único PIN por usuario.

Tenga en cuenta, también, que los PIN duplicados no son en sí mismos un problema: cualquier ataque simplemente tendría que probar múltiples ID de usuario.

(Advertencia de kilometraje: Definitivamente no soy un experto en seguridad).

Aquí hay una segunda respuesta: a partir de la relectura, supongo que no desea una identificación de usuario como tal; solo está validando un conjunto de tarjetas de borrador emitidas. También asumo que no quieres usar PIN alfabéticos.

Debe elegir una longitud de PIN para que la probabilidad de adivinar un PIN válido sea inferior a 1 / (la cantidad de intentos contra los que puede proteger). Entonces, por ejemplo, si tiene 1 millón de PIN válidos y desea proteger contra 10000 conjeturas, necesitará un PIN de 10 dígitos.

Si usa la versión de John Graham-Cumming del sistema Perfect Paper Passwords , puede:

  1. Configure esto para (digamos) pines decimales de 10 dígitos
  2. Elija una frase secreta IV / clave
  3. Generar (decir) el primer millón de contraseñas (/ PIN)

Sospecho que este es un procedimiento genérico que podría, por ejemplo, ser usado para generar identificadores de productos 25-alfanuméricos también.

Perdón por hacerlo por una aproximación sucesiva; Espero que se acerque un poco a lo que estás buscando.


4 dígitos aleatorios deberían ser suficientes si los agrega a un único ID de usuario conocido (podría ser el número) [recomendado por starblue]

El generador de números pseudoaleatorios también debería estar bien. Puede almacenarlos en la base de datos utilizando cifrado reversible (AES) o hash unidireccional

La principal preocupación que tiene es cuántas veces una persona puede ingresar incorrectamente el pin antes de que se bloqueen. Esto debería ser bajo, digamos alrededor de las tres ... Esto evitará que la gente adivine los números de otras personas.

Más de 6 dígitos y las personas los olvidarán, o lo que es peor, los escribirán en una nota de post-it en su monitor.

Suponiendo que una cuenta se bloquea con 3 intentos incorrectos, entonces tener un pin de 4 dígitos más un ID de usuario UserId (999999) + Pin (1234) te da una probabilidad 3/10000 de que alguien adivine. ¿Es esto aceptable? Si no, haga la longitud del pin 5 y obtenga 3/100000


Existe una diferencia entre adivinar el PIN de un usuario objetivo y el de cualquier usuario válido. Desde su caso de uso, parece que el PIN se usa para obtener acceso a cierto recurso, y es ese recurso que los atacantes pueden buscar, no las identidades particulares de los usuarios. Si ese es realmente el caso, deberá establecer números PIN válidos suficientemente dispersos entre todos los números posibles de los mismos dígitos numéricos.

Como se menciona en algunas respuestas, debe hacer que su PIN sea lo suficientemente aleatorio, independientemente de si desea generarlo a partir de un algoritmo. La aleatoriedad generalmente se mide por la entropía del PIN.

Ahora, digamos que su PIN es de entropía N , y hay 2 ^ M usuarios en su sistema ( M <N ), la probabilidad de que una conjetura aleatoria arroje un PIN válido es 2 ^ {MN} . (Perdón por las notaciones de látex, espero que sea lo suficientemente intuitivo). Luego, desde allí puede determinar si esa probabilidad es lo suficientemente baja dado N y M , o calcular el N requerido a partir de la probabilidad deseada y M.

Hay varias maneras de generar los PIN para que no tenga que recordar cada PIN que generó. Pero necesitará un PIN muy largo para hacerlo seguro. Esto probablemente no es lo que quieres.


La pregunta debería ser: "¿Cuántas suposiciones son necesarias en promedio para encontrar un código PIN válido, en comparación con la cantidad de intentos que hacen los atacantes?"

Si genera 100 000 códigos de 5 dígitos, obviamente se necesita 1 suposición. Es poco probable que sea lo suficientemente bueno.

Si genera 100 000 códigos de n dígitos, entonces se necesitan (n-5) ^ 10 conjeturas. Para determinar si esto es lo suficientemente bueno, debe considerar cómo responde su sistema a una suposición errónea.

Si un atacante (o todos los atacantes combinados) puede hacer 1000 intentos por segundo, entonces claramente debe ser bastante grande para detener a un atacante determinado. Si bloqueas permanentemente su dirección IP luego de 3 conjeturas incorrectas, entonces dado que es poco probable que un atacante determinado tenga acceso a más de, digamos, 1000 direcciones IP, n = 9 sería suficiente para frustrar a casi todos los atacantes. Obviamente, si enfrenta ataques distribuidos o ataques desde una botnet, entonces 1000 direcciones IP por atacante ya no son una suposición segura.

Si en el futuro necesita emitir más códigos (más de 100 000), entonces obviamente hace que sea más fácil adivinar un código válido. Por lo tanto, probablemente valga la pena pasar algún tiempo asegurándose de sus futuras necesidades de escalamiento antes de corregir un tamaño.

Dado el caso de uso de su tarjeta rasca y gana, si los usuarios van a utilizar el sistema durante mucho tiempo, les recomendaría permitir (u obligarlos) a "actualizar" su código PIN a un nombre de usuario y contraseña de su elección después del primer uso del sistema. Luego obtienes las ventajas habituales de nombre de usuario / contraseña, sin descartar la facilidad del primer uso de simplemente escribir el número de la tarjeta.

En cuanto a cómo generar el número, presumiblemente cada uno que genere lo almacenará, en cuyo caso yo diría que los genera al azar y descarta los duplicados. Si los genera usando cualquier tipo de algoritmo, y alguien averigua el algoritmo, entonces pueden descubrir códigos PIN válidos. Si selecciona un algoritmo tal que no es posible que alguien descubra el algoritmo, entonces eso es casi un generador de números pseudoaleatorios (la otra propiedad de los PRNG es que están distribuidos uniformemente, lo que ayuda aquí también, ya que lo hace más difícil de adivinar códigos), en cuyo caso también podría generarlos al azar.


Parece que desea utilizar el código PIN como único medio de identificación para los usuarios. Una solución viable sería usar los primeros cinco dígitos para identificar al usuario y agregar cuatro dígitos como código PIN.

Si no desea almacenar los PIN, se pueden calcular aplicando un hash criptográficamente seguro (SHA1 o mejor) al número de usuario más un código secreto de todo el sistema.


Si asumimos 100.000 usuarios como máximo, entonces pueden tener PIN únicos con 0-99,999, es decir. 5 dígitos

Sin embargo, esto haría que sea más fácil adivinar los PIN con la cantidad máxima de usuarios. Si puede restringir el número de intentos en el PIN, entonces puede tener un PIN más corto. p.ej. un máximo de 10 intentos fallidos por IP por día.

También depende del valor de lo que está protegiendo y de lo catastrófico que sería si se saliera alguno.

Me gustaría obtener 9 dígitos si desea mantenerlo corto o 12 dígitos si desea un poco más de seguridad de las adivinanzas automáticas.

Para generar los PIN, tomaría una versión de alta resolución del tiempo junto con un poco de sal y tal vez un número pseudoaleatorio, generaría un hash y usaría los primeros 9 o 12 dígitos. Asegúrese de que haya un retraso razonable y aleatorio entre las nuevas generaciones de PIN, por lo que no las genere en un bucle y, si es posible, haga que el usuario lo inicie.

p.ej. Izquierda (Sha1 (DateTime + Salt + PseudoRandom), 9)


¡Muchas respuestas excelentes hasta ahora: simples, efectivas y elegantes!

Supongo que la aplicación es similar a una lotería, en la que cada usuario obtiene una tarjeta rasca y la usa para preguntarle a su aplicación si "¡ya ganó!" Entonces, desde esa perspectiva, algunos problemas nuevos vienen a la mente:

War-diking , o su equivalente en Internet: ¿Puede un usuario deshonesto golpear su aplicación repetidamente, digamos adivinar cada número de 10 dígitos en sucesión? Si eso es una posibilidad, considere limitar el número de intentos desde una ubicación particular. Una forma efectiva podría ser simplemente negarse a responder más que, por ejemplo, un intento cada 5 segundos desde la misma dirección IP. Esto hace que los ataques dirigidos por la máquina sean ineficientes y evita el problema de bloqueo .

Problema de bloqueo : si bloquea una cuenta permanentemente después de una cantidad de intentos fallidos, es propenso a ataques de denegación de servicio . El atacante anterior podría bloquear efectivamente a todos los usuarios a menos que reactive las cuentas después de un período de tiempo. Pero esto es un problema solo si sus PIN consisten en una concatenación obvia de ID de usuario + clave, porque un atacante podría probar cada clave para una ID de usuario determinada. Esa técnica también reduce drásticamente el espacio de clave, ya que solo unos pocos dígitos del PIN son realmente aleatorios. Por otro lado, si el PIN es simplemente una secuencia de dígitos aleatorios, el bloqueo solo debe aplicarse a la dirección IP de origen. (Si falla un intento, ninguna cuenta válida se ve afectada, entonces, ¿qué "bloquearía"?)

Almacenamiento de datos : si realmente está construyendo algún tipo de sistema tipo lotería, ¡ solo necesita almacenar los PIN ganadores ! Cuando un usuario introduce un PIN, puede buscar una lista relativamente pequeña de PIN / premios (o su equivalente). Puede tratar los PIN "perdidos" y no válidos de forma idéntica con un mensaje de "Perdón, mejor suerte la próxima vez" o un premio "predeterminado" si los aspectos económicos son correctos.

¡Buena suerte!


He hecho esto antes con PHP y una base de datos MySQL. Tenía una función de permutaciones que primero aseguraría que la cantidad de códigos requeridos - $ n, a la larga $ l, con el número de caracteres, $ c - pudiera crearse antes de comenzar el proceso de generación.

Luego, almacenaba cada nuevo código en la base de datos y dejaba que me diga, mediante errores UNIQUE KEY, que hubo una colisión (duplicado). Luego continúe hasta que haya creado $ n número de códigos creados correctamente. Por supuesto, podría hacer esto en la memoria, pero quería conservar los códigos para utilizarlos en una combinación de correspondencia de MS Word. Entonces ... luego los exporté como un archivo CSV.


Si desea generar códigos pin tipo scratch-card, entonces debe usar números grandes, de alrededor de 13 dígitos; y también, deben ser similares a los números de tarjetas de crédito, con una suma de verificación o dígito de verificación incrustado en el número mismo. Debe tener un algoritmo para generar un pin basado en algunos datos iniciales, que pueden ser una secuencia de números. El pin resultante debe ser único para cada número de la secuencia, de modo que si genera 100.000 códigos pin, todos deben ser diferentes. De esta forma, podrá validar un número no solo al compararlo con una base de datos, sino también puede verificarlo primero.

Una vez escribí algo para ese propósito, no puedo darte el código pero la idea general es esta:

  • Prepare un espacio de 12 dígitos
  • Formatee el número como cinco dígitos (00000 a 99999) y extiéndalo a lo largo del espacio de cierta manera. Por ejemplo, el número 12345 se puede extender como __3_5_2_4__1. Puede variar la forma en que distribuye el número dependiendo de si es un número par o impar, o un múltiplo de 3, etc.
  • En función del valor de ciertos dígitos, genere más dígitos (por ejemplo, si el tercer dígito es par, cree un número impar y colóquelo en el primer espacio abierto, de lo contrario, cree un número par y colóquelo en el segundo espacio abierto, por ejemplo _83_5_2_4__1
  • Una vez que haya generado 6 dígitos, tendrá solo un espacio abierto. Siempre debe dejar el mismo espacio abierto (por ejemplo, el penúltimo espacio). Colocarás el dígito de verificación en ese lugar.
  • Para generar el dígito de verificación, debe realizar algunas operaciones aritméticas en el número que ha generado, por ejemplo, sumar todos los dígitos en las posiciones impares y multiplicarlos por otro número, luego restar todos los dígitos en las posiciones pares y finalmente agregar todo los dígitos juntos (debe variar el algoritmo un poco en función del valor de ciertos dígitos). Al final, tiene un dígito de verificación que incluye en el código PIN generado.

Entonces ahora puedes validar tus códigos PIN generados. Para un código pin dado, usted genera el dígito de verificación y lo compara con el que está incluido en el pin. Si está bien, entonces puedes extraer el número original realizando las operaciones inversas.

No suena tan bien porque parece una seguridad a través de la oscuridad, pero es la única forma en que puedes usar esto. No es imposible que alguien adivine un código PIN, pero al ser un código de 12 dígitos con un dígito de verificación, será muy difícil ya que tienes que probar 1,000,000,000,000 de combinaciones y solo tienes 100,000 códigos pin válidos, así que para cada código PIN válido allí son 10,000,000 inválidos.

Debo mencionar que esto es útil para los códigos PIN desechables; una persona usa uno de estos códigos solo una vez, por ejemplo, para cargar un teléfono prepago. No es una buena idea usar estos pines como tokens de autenticación, especialmente si es la única forma de autenticar a alguien (nunca debes autenticarte NUNCA con un solo dato, el mínimo es nombre de usuario + contraseña)


Si usa algoritmos de generador de números aleatorios, para que nunca tenga un PIN como "00038384882", comienza con 0 (ceros), porque los números enteros nunca comienzan con "0". su PIN debe comenzarse con 1-9 números, excepto 0.

He visto muchos números de PIN incluidos y comienza muchos ceros, por lo que elimina el primer millón de números. Permutación necesita cálculos para cuántos números eliminados.

Creo que necesitas poner 0-9 números en un hash, y obtener al azar de hash, y hacer que su número PIN de cadena.