Clave de licencia / generador de números de serie y verificador

16

Necesito un generador de números de serie y un comprobador de acompañamiento. Me gustaría poder establecer una sal (y quizás una longitud). El generador solo debe producir números de serie que pasen la prueba del verificador. Esos números solo deben representar una pequeña fracción de todos los números posibles de la longitud dada.

El algoritmo no necesita ser criptográficamente seguro . Más bien, debería ser muy fácil de implementar (en javascript) y debería ser muy rápido.

Para aclarar: si compra software comercial, a veces está protegido con un número de serie / clave. Si lo escribe, el software lo verifica algorítmicamente (verificando si cumple con ciertas propiedades), en lugar de buscar una gran base de datos. También estoy bastante seguro de que todas las claves se generaron algorítmicamente en lugar de a mano. Y solo una pequeña fracción de todas las claves posibles de una longitud determinada son realmente válidas, por lo que es difícil de adivinar las claves.

Sal: no sé si sal es la palabra correcta, pero el algoritmo debe tener al menos un parámetro, cuya opción altera las claves generadas (para que varias personas puedan usar el mismo algoritmo y no tengan que temer las colisiones) .

    
pregunta Dave 07.03.2011 - 03:37
fuente

3 respuestas

25

Si no existe una necesidad real de seguridad, aquí hay un generador de números de serie muy rápido, con un comprobador:

  • Usuario un contador. Inicialícelo en 0. Cuando desee un nuevo número de serie, incremente su contador en 1000; El nuevo valor del contador es el número de serie. El verificador funciona así: un número de serie es válido si termina con tres ceros. El verificador solo aceptará uno de cada 1000 números.

Si esta solución no le satisface, entonces necesita seguridad, y esto requiere criptografía.

La solución criptográficamente segura es tener números de serie firmados: el número de serie es la codificación de cierta carga útil (por ejemplo, un contador de todos los números de serie que usted ha generado) y una firma sobre la carga útil. El generador tiene una clave privada, que utiliza para calcular las firmas; El verificador solo conoce la clave pública correspondiente. El problema con esta configuración no es realmente acerca del tiempo de verificación, incluso en Javascript; más bien, es el tamaño de la firma lo que constituye un problema. Supongo que el número de serie será, en algún momento, escrito por un usuario. El tamaño teórico mínimo para una firma criptográficamente segura es de aproximadamente 80 bits (ya que las firmas se pueden verificar solo con la clave pública, un atacante podría probar todas las secuencias de bits posibles, y generalmente requerimos un nivel de seguridad de al menos 2 80 ). Sin embargo, las firmas más pequeñas entre los "supuestos esquemas seguros" están más cerca de 160 bits (con BLS , que utiliza un emparejamiento, que es un poco complejo de implementar) o 320 bits (con DSA o ECDSA ). Hay algunos trabajos sobre sistemas de firmas con firmas más cortas ( Quartz , o McEliece-Niederreiter ) pero existe bastante controversia sobre su seguridad.

Incluso con letras y dígitos en mayúsculas (36 caracteres posibles, y allí tiene 'I' y '1', y también 'O' y '0'), una firma de 160 bits utilizará 31 caracteres. Junto con la carga útil, terminará con números de serie de longitud 35 o más, lo que probablemente sea demasiado para que un usuario promedio escriba (pero no por un gran margen; una firma de 80 bits encajaría muy bien).

Si no usa un esquema de firma, debe tener en cuenta que un atacante razonablemente determinado podrá, mediante un desmontaje, eludir el comprobador o incluso aprender lo suficiente para poder para producir sus propios números de serie (que el verificador aceptará felizmente). En ese momento, no obtendrá seguridad cuantificada: no podrá decir: "mi plan es seguro hasta un presupuesto de 3.800 millones de dólares". Más bien, irá como: "mi plan es seguro hasta que aparece un estudiante suficientemente ingenioso y aburrido, realiza una ingeniería inversa del código del verificador y publica el resultado en Facebook".

El esquema clásico no muy seguro se vería así:

  • Use el contador del esquema anterior (el que tiene extremos con tres ceros). Codifíquelo como un bloque de 64 bits. Cifre ese bloque con una clave simétrica codificada mediante un cifrado de bloque. El verificador conoce la clave y verifica el número de serie descifrando (con la misma clave simétrica codificada) y mirando los ceros finales.

Esto no es realmente más seguro que el contador simple, pero al menos los números de serie tendrán un aspecto aleatorio. Con un alfabeto de 34 caracteres (dígitos y letras mayúsculas excepto 'O' e 'I'), un bloque de 64 bits requiere 13 letras, lo que probablemente sea aceptable (un número de serie típico de Microsoft tiene 25 letras). Para el cifrado de bloque de 64 bits, recomiendo XTEA , que debería ser lo suficientemente rápido y sencillo de implementar.

    
respondido por el Thomas Pornin 07.03.2011 - 15:02
fuente
6

Si desea el método criptográfico seguro, no podrá conectarse a Internet para verificar la serie. Esto significa que tal esquema de protección es más adecuado para el software basado en suscripción que para el software de estantería tradicional.

Con las conexiones a Internet es simple (ya que usa JS, supongo que es la que desea):

  1. Alguien crea una clave, esa parte debe conocer el secreto
  2. El servidor conoce el secreto y puede decodificar los datos
  3. El cliente envía la clave, que es un blob binario codificado en Base32 (también vea this )
  4. El servidor descifra la clave y comprueba si es válida (ya sea de manera sintáctica o semántica)

Sin conexión a Internet, puedes seguir usando un esquema similar al de la firma PGP para verificar que el blob que ingresa el usuario fue creado por ti. El cifrado no funcionará de la misma manera, ya que el descifrado siempre requiere conocer el secreto y el gran problema aquí es:

  1. no confía en el usuario (de lo contrario no necesitaría el esquema de protección)
  2. le da al usuario el secreto, compilado en su binario

Obviamente ambos puntos se contradicen entre sí. Por un lado, no confías en el usuario, por otro lado tienes que implementar el secreto utilizado para el descifrado.

En general, tengo que concluir que sin la conexión a Internet y la verificación de validez basada en el servidor que resulta en la revelación de algunos conocimientos (por ejemplo, contenido que es útil solo por mucho tiempo) cualquier esquema de protección que haya visto Hasta ahora es más o menos una carrera de armamentos entre crackers y proveedores.

Ahora, si no es importante tener un sistema criptográficamente seguro, seguiría buscando datos binarios que pueda proteger por medio de un simple CRC o algo así. Lo que viene a la mente sería:

  1. Tener un número de serie monotónicamente creciente
  2. XOR con su valor de sal (o cualquier otra operación reversible)
  3. Tome el CRC32 de ese valor (o Adler32 o lo que sea): agregue más sal aquí si es necesario
  4. Codifíquelo con Base32 (ayuda a la lectura, etc.)
  5. Solo verifique que el CRC32 tenga validez ...
respondido por el 0xC0000022L 07.03.2011 - 15:49
fuente
3

OP escribió "debería ser muy fácil de implementar (en javascript) y debería ser muy rápido"

No está claro si "in javascript" se refiere al generador o el verificador o ambos, o si se refiere a "javascript en el navegador", o alguna otra implementación de java / ecmascript (por ejemplo, servidor en el servidor web) .

Javascript como lenguaje de implementación no es necesariamente un problema, y hay un par de bibliotecas criptográficas para javascript (compatibles con MD5, DES, AES, SHA, PBKDF2, HMAC):

La velocidad tampoco debería ser un gran problema (los motores de javascript del navegador se están volviendo bastante útiles a este respecto, una vez que superas IE6 / 7).

Sin embargo, ninguno de los anteriores admite la criptografía de la clave pública (que se requiere para la seguridad si el "verificador" se distribuye al usuario que no es de confianza y, por lo tanto, no se puede permitir el acceso a la clave utilizada para crear números de serie). algoritmos sugeridos por Thomas, arriba. Google muestra algunos resultados para implementaciones de clave pública en JavaScript (http://www-cs-students.stanford.edu/~tjw/jsbn/, enlace , enlace ) pero personalmente estaría aún más nervioso por su error- libertad que las bibliotecas "más grandes" de arriba.

Quizás de manera más significativa, incluso con un enfoque basado en clave pública, si el generador o el verificador se distribuyen al usuario no confiable, entonces el esquema no es seguro. Si el código generador está disponible para el usuario que no es de confianza, entonces pueden generar tantas claves como deseen, mientras que si el verificador está disponible para el usuario que no es de confianza, simplemente pueden modificar el código de javascript para omitir las comprobaciones. [El mismo problema surge con el código nativo, por supuesto, pero, incluso con la ofuscación, se puede decir que JavaScript es más fácil de atacar a través de modificaciones locales.]

Antes de implementar un esquema de seguridad en JavaScript, también debe considerar los problemas de confianza más amplios: consulte enlace para un resumen útil.

    
respondido por el Misha 27.11.2011 - 13:35
fuente

Lea otras preguntas en las etiquetas