Pregunta

Estoy trabajando en una aplicación donde los usuarios tienen que hacer una llamada y escribir un número de verificación con el teclado de su teléfono.

Me gustaría poder detectar si el número que escriben es correcto o no.El sistema telefónico no tiene acceso a una lista de números válidos, sino que validará el número con un algoritmo (como un número de tarjeta de crédito).

Éstos son algunos de los requisitos:

  • Debe ser difícil escribir un código aleatorio válido.
  • Debe ser difícil tener un código válido si cometo un error tipográfico (transposición de dígitos, dígito incorrecto)
  • Debo tener un número razonable de combinaciones posibles (digamos 1M)
  • El código debe ser lo más corto posible, para evitar errores por parte del usuario.

Dados estos requisitos, ¿cómo generaría ese número?

EDITAR :

@Haaked:El código tiene que ser numérico porque el usuario lo escribe con su teléfono.

@matt b:En el primer paso, el código se muestra en una página web, el segundo paso es llamar y escribir el código.No sé el número de teléfono del usuario.

Hacer un seguimiento :He encontrado varios algoritmos para controlar la validez de los números (consulte este interesante proyecto de Google Code: comprobarDígitos).

¿Fue útil?

Solución

Después de investigar un poco, creo que optaré por el ISO 7064 Mod 97,10 fórmula.Parece bastante sólido ya que se utiliza para validar el IBAN (Número de cuenta bancaria internacional).

La fórmula es muy sencilla:

  1. Tome un número : 123456
  2. Aplique la siguiente fórmula para obtener la suma de verificación de 2 dígitos: mod(98 - mod(number * 100, 97), 97) => 76
  3. Número de concat y suma de comprobación para obtener el código => 12345676
  4. Para validar un código, verifique que mod(code, 97) == 1

Prueba :

  • mod(12345676, 97) = 1 => BUENO
  • mod(21345676, 97) = 50 => ¡MALO!
  • mod(12345678, 97) = 10 => ¡MALO!

Aparentemente, este algoritmo detecta la mayoría de los errores.

Otra opción interesante fue la Algoritmo de Verhoeff.Tiene solo un dígito de verificación y es más difícil de implementar (en comparación con la fórmula simple anterior).

Otros consejos

Para combinaciones de 1 millón necesitarás 6 dígitos.Para asegurarse de que no haya códigos válidos accidentalmente, sugiero 9 dígitos con una probabilidad de 1/1000 de que un código aleatorio funcione.También sugeriría usar otro dígito (10 en total) para realizar una verificación de integridad.En cuanto a los patrones de distribución, el azar será suficiente y el dígito de control garantizará que un solo error no dé como resultado un código correcto.

Editar: Aparentemente no leí completamente su solicitud.Usando un número de tarjeta de crédito, puede realizar un hash (MD5 o SHA1 o algo similar).Luego trunca en un lugar apropiado (por ejemplo, 9 caracteres) y convierte a base 10.Luego agrega los dígitos de control y esto debería funcionar más o menos para sus propósitos.

Quieres segmentar tu código.Parte de él debería ser un CRC de 16 bits del resto del código.

Si todo lo que desea es un número de verificación, simplemente use un número de secuencia (suponiendo que tenga un único punto de generación).De esa manera sabrás que no obtendrás duplicados.

Luego, antepone la secuencia con un CRC-16 de ese número de secuencia Y alguna clave privada.Puedes usar cualquier cosa para la clave privada, siempre y cuando la mantengas privada.Hazlo algo grande, al menos un GUID, pero podría ser el texto para Guerra y paz del proyecto Gutenberg.Sólo necesita ser secreto y constante.Tener una clave privada impide que las personas puedan falsificar una clave, pero usar un CR de 16 bits hace que sea más fácil descifrar.

Para validar, simplemente divide el número en dos partes y luego toma un CRC-16 del número de secuencia y la clave privada.

Si desea oscurecer más la parte secuencial, divida el CRC en dos partes.Coloque 3 dígitos al frente y 2 al final de la secuencia (rellene cero para que la longitud del CRC sea consistente).

Este método también le permite comenzar con claves más pequeñas.Las primeras 10 claves serán de 6 dígitos.

¿Tienen que ser sólo números?Podrías crear un número aleatorio entre 1 y 1M (aunque sugeriría incluso más alto) y luego Base32 lo codifica.Lo siguiente que debe hacer es codificar ese valor (usando un valor de sal secreto) y codificar en base32 el hash.Luego, une las dos cadenas, quizás separadas por un guión.

De esa manera, puedes verificar el código entrante algorítmicamente.Simplemente toma el lado izquierdo del código, aplica un hash usando tu sal secreta y compara ese valor con el lado derecho del código.

  • Debo tener un número razonable de combinaciones posibles (digamos 1M)
  • El código debe ser lo más corto posible, para evitar errores por parte del usuario.

Bueno, si quieres que tenga al menos un millón de combinaciones, entonces necesitas al menos seis dígitos.¿Es eso lo suficientemente corto?

Cuando crea el código de verificación, ¿tiene acceso al número de teléfono de la persona que llama?

Si es así, usaría el número de teléfono de la persona que llama y lo ejecutaría a través de algún tipo de función hash para que pueda garantizar que el código de verificación que le dio a la persona que llama en el paso 1 es el mismo que ingresa en el paso 2 (para asegurarse no están usando el código de validación de un amigo o simplemente hicieron una suposición muy afortunada).

En cuanto al hash, no estoy seguro de si es posible tomar un número de 10 dígitos y obtener un resultado hash que sería <10 dígitos (supongo que tendrías que vivir con una cierta cantidad de colisión), pero creo esto ayudaría a garantizar que el usuario sea quien dice ser.

Por supuesto, esto no funcionará si el número de teléfono utilizado en el paso 1 es diferente al que llaman en el paso 2.

Suponiendo que ya sepa cómo detectar qué tecla presionó el usuario, esto debería ser factible con razonable facilidad.En el mundo de la seguridad, existe la noción de contraseña de "un solo uso".Esto a veces se conoce como una "contraseña desechable". Normalmente estos están restringidos a los valores ASCII (fácilmente tipeables).Entonces, [a-zA-z0-9] y un montón de símbolos fáciles de escribir.como coma, punto, punto y coma y paréntesis.Sin embargo, en su caso, probablemente desee limitar el rango a [0-9] y posiblemente incluir * y #.

No puedo explicar todos los detalles técnicos de cómo se generan (o funcionan) adecuadamente estos códigos de un solo uso.Hay algunas matemáticas intermedias detrás de esto, que destruiría sin revisarlas primero yo mismo.Baste decir que utiliza un algoritmo para generar un flujo de contraseñas de un solo uso.No importa cuántos códigos anteriores conozcas, ¡el siguiente debería ser imposible de adivinar!En su caso, simplemente utilizará cada contraseña de la lista como código aleatorio del usuario.

En lugar de no poder explicar los detalles de la implementación yo mismo, lo remitiré a un artículo de 9 páginas donde puede leerlo usted mismo: https://www.grc.com/ppp.htm

Parece que tiene el requisito tácito de que se debe determinar rápidamente, mediante un algoritmo, que el código es válido.Esto descartaría que usted simplemente entregue una lista de números de bloc de notas de un solo uso.

Hay varias formas en que la gente ha hecho esto en el pasado.

  1. Haga una clave pública y una clave privada.Codifique los números 0-999,999 usando la clave privada y entregue los resultados.Tendrás que introducir algunos números aleatorios para que el resultado salga a la versión más larga y tendrás que convertir el resultado de base 64 a base 10.Cuando ingrese un número, conviértalo nuevamente a base64, aplique la clave privada y vea si los números interesantes están por debajo de 1,000,000 (descarte los números aleatorios).
  2. Usar una función hash reversible
  3. Utilice el primer millón de números de un PRN sembrado en un valor específico.La función de "verificación" puede obtener la semilla y saber que el siguiente millón de valores son buenos.Puede generarlos cada vez y verificarlos uno por uno cuando se recibe un código, o al iniciar el programa almacenarlos todos en una tabla, ordenarlos y luego usar la búsqueda binaria (máximo de comparaciones), ya que un millón de números enteros no es mucho. del espacio.

Hay muchas otras opciones, pero son comunes y fáciles de implementar.

-Adán

Te vinculaste al dígitos de control proyecto, y usar la función "codificar" parece una buena solución.Dice:

La codificación puede generar una excepción si hay datos "malos" (p. ej.no numérico), mientras que verificar solo devuelve verdadero o falso.La idea aquí es que encode normalmente obtiene sus datos de fuentes internas "confiables" (una clave de base de datos, por ejemplo), por lo que debería ser bastante habitual, de hecho, excepcional que se pasen datos incorrectos.

Entonces, parece que podría pasar a la función de codificación una clave de base de datos (5 dígitos, por ejemplo) y podría obtener un número que cumpliera con sus requisitos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top