language agnostic - decodificador - 1-1 mapeos para ofuscación id
w3c encode url (8)
Agregue un campo char (10) a su tabla de órdenes ... llámelo ''order_number''.
Después de crear una nueva orden, genere aleatoriamente un número entero de 1 ... 9999999999. Verifique si existe en la base de datos bajo ''order_number''. De lo contrario, actualice su última fila con este valor. Si existe, elija otro número al azar.
Use ''order_number'' para las URL visibles públicamente, tal vez siempre llenas de ceros.
Hay un problema de condición de carrera para cuando dos hilos intentan agregar el mismo número al mismo tiempo ... podrías hacer un bloqueo de mesa si estuvieras realmente preocupado, pero eso es un gran martillo. Agregue una segunda comprobación después de la actualización, vuelva a seleccionarla para asegurarse de que sea única. Llamar recursivamente hasta que obtenga una entrada única. Permanezca durante un número aleatorio de milisegundos entre llamadas, y use la hora actual como una semilla para el generador de números aleatorios.
Sacado de aquí .
ACTUALIZADO Al igual que con el uso del enfoque GUID descrito por Bevan, si la columna está restringida como única, entonces no tiene que preocuparse. Supongo que esto no es diferente de usar un GUID, excepto que al cliente y al Servicio al cliente le será más fácil hacer referencia al pedido.
Estoy utilizando identificadores secuenciales como claves principales y hay casos en los que no quiero que esos identificadores sean visibles para los usuarios, por ejemplo, podría querer evitar las URL como? Invoice_id = 1234 que permiten a los usuarios adivinar cuántas facturas el sistema como un todo está emitiendo.
Podría agregar un campo de base de datos con un GUID o algo conjurado a partir de funciones de hash, cadenas aleatorias y / o conversiones de base numérica, pero los esquemas de ese tipo tienen tres problemas que me resultan molestos:
Tener que asignar el campo de base de datos adicional. Sé que podría usar el GUID como mi clave principal, pero mis PK enteros de incremento automático son lo correcto para la mayoría de los propósitos, y no quiero cambiar eso.
Tener que pensar en la posibilidad de colisiones hash / GUID. Doy mi total asentimiento a todos los argumentos sobre las colisiones GUID que son tan probables como la combustión espontánea o lo que sea, pero ignorar los casos excepcionales porque son excepcionales va en contra de todo lo demás que me han enseñado, y continúa molestándome incluso cuando sé Debería estar más preocupado por otras cosas.
No sé cómo recortar con seguridad los identificadores basados en hash, por lo que incluso si mis identificadores privados son de 16 o 32 bits, estoy atascado con identificadores generados de 128 bits que son una molestia en las URL.
Me interesan 1-1 las asignaciones de un rango de id, estirable o contraíble, de modo que, por ejemplo, los identificadores de 16 bits se asignan a identificadores de 16 bits, identificadores de 32 bits mapeados a identificadores de 32 bits, etc., y eso evitaría que alguien lo intentara adivinar el número total de identificadores asignados o la tasa de asignación de id. durante un período.
Por ejemplo, si mis identificadores de usuario son enteros de 16 bits (0..65535), entonces un ejemplo de una transformación que ofusca de algún modo la asignación de identificación es la función f (x) = (x mult 1001) mod 65536. La secuencia de identificación interna de 1, 2, 3 se convierte en la secuencia de identificación pública de 1001, 2002, 3003. Con una capa adicional de oscurecimiento de la conversión de base, por ejemplo a la base 36, la secuencia se convierte en ''rt'', ''1jm'', ''2bf''. Cuando el sistema recibe una solicitud para la url? Userid = 2bf, convierte de la base 36 a la 3003 y aplica la transformación inversa g (x) = (x mult 1113) mod 65536 para volver a la id interna = 3.
Un esquema de ese tipo es suficiente para detener la observación casual por parte de usuarios casuales, pero es fácilmente solucionable por alguien que esté lo suficientemente interesado como para intentar descifrarlo. ¿Alguien puede sugerir algo que es un poco más fuerte, pero es fácilmente implementable en PHP sin bibliotecas especiales? Esto se está acercando a un esquema de encriptación de rollo propio, por lo que tal vez haya un algoritmo de encriptación adecuado que esté ampliamente disponible y que tenga la propiedad de estirabilidad mencionada anteriormente.
EDITAR: Retrocediendo un poco, una discusión en codinghorror sobre elegir entre tres tipos de claves: sustituto (basado en la guía), sustituto (basado en el entero), natural. En esos términos, trato de ocultar una clave suplente entera de los usuarios, pero estoy buscando algo que se pueda contraer y que haga que las URL no sean demasiado largas, lo que no sé hacer con el GUID estándar de 128 bits . A veces, como comenta el comentarista Princess a continuación, el problema puede eludirse con una clave natural.
EDIT 2 / RESUMEN:
- Dadas las limitaciones de la pregunta que hice (extensibilidad, reversibilidad, facilidad de implementación), la solución más adecuada hasta ahora parece ser la ofuscación basada en XOR sugerida por Someone y Breton.
- Sería irresponsable por mi parte suponer que puedo lograr algo más que ofuscación / seguridad por oscuridad. El conocimiento de que se trata de una secuencia entera es probablemente una cuna que cualquier atacante competente podría aprovechar.
- He reflexionado un poco más sobre la idea del campo de base de datos adicional. Una ventaja del campo adicional es que lo hace mucho más sencillo para los futuros programadores que intentan familiarizarse con el sistema mirando la base de datos. De lo contrario, tendrían que buscar el código fuente (o la documentación, ejem) para determinar cómo se resuelve una solicitud a una url determinada a un registro dado en la base de datos.
- Si permito el campo de base de datos adicional, entonces algunas de las otras suposiciones en la pregunta se vuelven irrelevantes (por ejemplo, la transformación no necesita ser reversible). Eso se convierte en una pregunta diferente, así que lo dejaré allí. Gracias a todos por compartir sus ideas.
Desde su descripción, personalmente, comenzaría trabajando con cualquier biblioteca de cifrado estándar disponible (soy un programador de Java, pero supongo que, por ejemplo, una biblioteca de cifrado AES básica debe estar disponible para PHP):
- en la base de datos, solo cosas clave como lo harías normalmente
- cada vez que necesite transmitir una clave a / desde un cliente, utilice un sistema de cifrado estándar bastante sólido (por ejemplo, AES) para convertir la clave a / desde una cadena de basura. Como texto sin formato, use un (digamos) búfer de 128 bytes que contenga: una (digamos) clave de 4 bytes, 60 bytes aleatorios y luego un hash de calidad media de 64 bytes de los 64 bytes anteriores (consulte Recetas numéricas para obtener un ejemplo): obviamente, cuando recibes una cadena de este tipo, la descifras y luego compruebas si el hash coincide antes de pulsar la base de datos. Si estás siendo un poco más paranoico, envía un búfer encriptado AES de bytes aleatorios con tu clave en una posición arbitraria, más un hash seguro de ese búfer como un parámetro separado. Sin embargo, la primera opción es una compensación razonable entre rendimiento y seguridad para sus propósitos, especialmente cuando se combina con otras medidas de seguridad.
- el día en que está procesando tantas facturas por segundo que AES las encripta en tránsito es demasiado caro, salga y cómpre un gran servidor con muchas CPU para celebrar.
Además, si desea ocultar que la variable es un ID de factura, puede considerar llamarlo de otra forma que no sea "invoice_id".
Encuentro que el cifrado simple XOR es más adecuado para la ofuscación de URL. Puede continuar usando cualquier número de serie que esté utilizando sin cambios. Además, el cifrado XOR no aumenta la longitud de la cadena fuente. Si su texto es de 22 bytes, la cadena cifrada también tendrá 22 bytes. No es tan fácil como para ser adivinado como rot 13 pero no de gran peso como DSE / RSA.
Busque en la red el cifrado PHP XOR para encontrar alguna implementación. El primero que encontré está aquí .
He jugado con este tipo de cosas yo mismo, a mi manera amateur, y llegué a un tipo de algoritmo de codificación de números chiflados, que involucraba radices mixtas. Básicamente tengo una función que mapea un número entre 0-N a otro número en el rango 0-N. Para URLS, luego asocie ese número a un par de palabras en inglés. (las palabras son más fáciles de recordar).
Una versión simplificada de lo que hago, sin radices mixtas: tiene un número que es de 32 bits, así que antes de tiempo, tenga una clave de acceso que tenga 32 bits de longitud, y XOR la clave con su número de entrada. Luego baraja los bits en un reordenamiento determinado. (posiblemente basado en su clave de acceso).
Lo bueno de esto es
- Sin colisiones, siempre y cuando mezcle y xor de la misma manera cada vez
- No es necesario almacenar las claves ofuscadas en la base de datos
- Todavía use su IDS ordenado internamente, ya que puede revertir la ofuscación
- Puede repetir la operación varias veces para obtener más resultados ofuscados.
si estás preparado para la versión mixta de radix, básicamente es la misma, excepto que agrego los pasos de convertir la entrada a un número de raddix mixto, usando los factores primos del rango máximo como las bases del dígito. Luego mezclo los dígitos, manteniendo las bases con los dígitos, y lo vuelvo a convertir en un entero estándar.
Puede que le resulte útil volver a considerar la idea de utilizar un GUID, ya que puede construir GUID de una manera que no esté sujeta a colisión.
Consulte la página de Wikipedia sobre GUIDs - el algoritmo "Tipo 1" usa tanto la dirección MAC de la PC como la fecha / hora actual como entradas. Esto garantiza que las colisiones son simplemente imposibles.
Alternativamente, si crea una columna GUID en su base de datos como una clave alternativa (siga usando sus claves primarias de incremento automático), defínnela como única. Entonces, si su enfoque de generación GUID da un duplicado, obtendrá un error apropiado en la inserción que puede manejar.
Sinceramente, el cifrado / descifrado de datos de cadena de consulta es un mal enfoque para este problema. La solución más fácil es enviar datos usando POST en lugar de GET. Si los usuarios hacen clic en enlaces con datos de cadena de consulta, debe recurrir a algunos hack de JavaScript para enviar datos por POST (tenga en cuenta la accesibilidad para los usuarios con Javascript desactivado). Esto no impide que los usuarios vean el código fuente, pero al menos los motores de búsqueda no los indexan, asumiendo que los datos que intenta ocultar son realmente tan sensibles desde el principio.
Otro enfoque es usar una clave única natural. Por ejemplo, si está emitiendo facturas mensualmente a clientes, entonces "aaaaMM [ID del cliente]" identifica de manera única una factura en particular para un usuario en particular.
Encontré una manera mucho más simple. Supongamos que quiere asignar N dígitos, pseudoaleatoriamente a N dígitos. usted encuentra el siguiente primer máximo de N, y usted hace su función
prandmap(x) return x * nextPrime(N) % N
esto producirá una función que repite (o tiene un período) cada N, no se produce ningún número dos veces hasta que x = N + 1. Siempre comienza en 0, pero es pseudoaleatorio a partir de entonces.
Ayer vi esta pregunta: cómo reddit genera una identificación alfanumérica
Creo que es un método razonablemente bueno (y particularmente ingenioso)
usa Python
def to_base(q, alphabet):
if q < 0: raise ValueError, "must supply a positive integer"
l = len(alphabet)
converted = []
while q != 0:
q, r = divmod(q, l)
converted.insert(0, alphabet[r])
return "".join(converted) or ''0''
def to36(q):
return to_base(q, ''0123456789abcdefghijklmnopqrstuvwxyz'')