Hay muchas aplicaciones donde se usa un generador de números pseudoaleatorios. Entonces, las personas implementan uno que piensan que es genial solo para descubrir más tarde que es defectuoso. Algo así sucedió recientemente con el generador de números aleatorios de Javascript. RandU mucho antes también. También hay problemas de siembra inicial inapropiada para algo como el Twister.
No puedo encontrar ejemplos de alguien que combine dos o más familias de generadores con el operador xor habitual. Si hay suficiente potencia de computadora para ejecutar cosas como las implementaciones java.SecureRandom o Twister, ¿por qué las personas no las combinan? ISAAC xor XORShift xor RandU debería ser un buen ejemplo, y donde se puede ver la debilidad de un único generador mitigado por los demás. También debería ayudar con la distribución de números en dimensiones superiores, ya que los algoritmos intrínsecos son totalmente diferentes. ¿Hay algún principio fundamental de que no deben combinarse?
Si construyera un verdadero generador de números aleatorios, las personas probablemente le aconsejarían que combine dos o más fuentes de entropía. ¿Mi ejemplo es diferente?
Estoy excluyendo el ejemplo común de varios registros de desplazamiento de retroalimentación lineal que trabajan juntos ya que son de la misma familia.
Respuestas:
IIRC (y esto es de memoria), el best-seller Rand de 1955 A Million Random Digits hizo algo como esto. Antes de que las computadoras fueran baratas, la gente escogió números aleatorios de este libro.
Los autores generaron bits aleatorios con ruido electrónico, pero resultó ser parcial (es difícil hacer que un flipflop pase exactamente el mismo tiempo en el flip y el flop). Sin embargo, la combinación de bits hizo que la distribución fuera mucho más uniforme.
fuente
Claro, puede combinar PRNG como este, si lo desea, suponiendo que se siembren de forma independiente. Sin embargo, será más lento y probablemente no resolverá los problemas más apremiantes que tiene la gente.
En la práctica, si tiene un requisito para un PRNG de muy alta calidad, utiliza un PRNG de fuerza criptográfica bien examinado y lo siembra con verdadera entropía. Si hace esto, su modo de falla más probable no es un problema con el algoritmo PRNG en sí mismo; El modo de falla más probable es la falta de entropía adecuada (o quizás errores de implementación). Hacer múltiples PRNG no ayuda con este modo de falla. Por lo tanto, si desea un PRNG de muy alta calidad, probablemente no tenga mucho sentido hacerlo.
Alternativamente, si desea un PRNG estadístico que sea lo suficientemente bueno para fines de simulación, por lo general, la preocupación número 1 es la velocidad (generar números pseudoaleatorios realmente rápidos) o la simplicidad (no desea dedicar mucho tiempo de desarrollo a investigarlo o implementarlo). Xor-ing ralentiza el PRNG y lo hace más complejo, por lo que tampoco aborda las necesidades primarias en ese contexto.
Siempre que exhiba un cuidado y competencia razonables, los PRNG estándar son más que suficientes, por lo que realmente no hay ninguna razón por la que necesitemos algo más elegante (no hay necesidad de xor-ing). Si no tiene niveles mínimos de atención o competencia, probablemente no va a elegir algo complejo como xor-ing, y la mejor manera de mejorar las cosas es centrarse en una mayor atención y competencia en la selección de la PRNG en lugar de en xor-ing.
En pocas palabras : Básicamente, el truco xor no resuelve los problemas de la gente por lo general tienen en realidad cuando se utiliza PRNG.
fuente
De hecho, se acaba de anunciar algo importante al hacer precisamente esto.
El profesor de informática de la Universidad de Texas David Zuckerman y el estudiante de doctorado Eshan Chattopadhyay descubrieron que se podía generar un número aleatorio de "alta calidad" combinando dos fuentes aleatorias de "baja calidad".
Aquí está su artículo: Extractores explícitos de dos fuentes y funciones resistentes
fuente
Supongamos que es una secuencia binaria pseudoaleatoria. Es decir, cada es una variable aleatoria compatible con , y las variables no son necesariamente independientes. Podemos pensar que esta secuencia se genera de la siguiente manera: primero muestreamos una clave aleatoria uniforme , y luego usamos alguna función para generar la secuencia pseudoaleatoria.X i { 0 , 1 } X 1 , ... , X n K f ( K )X1,…,Xn Xi {0,1} X1,…,Xn K f(K)
¿Cómo medimos qué tan buena es la secuencia pseudoaleatoria ? Si bien es posible medir qué tan buena es una realización particular (por ejemplo, usando la complejidad de Kolmogorov), aquí me concentraré en medidas que dependen de la distribución completa de la variable aleatoria . Un ejemplo de ello es la entropía, pero solo necesitaremos dos propiedades de nuestra medida : (una más grande significa una secuencia más aleatoria) ( X 1 , ... , X n ) L L ( ⋅ )X1,…,Xn (X1,…,Xn) L L(⋅)
Si es una secuencia determinista (es decir, una secuencia fija), entonces . L ( X 1 ⊕ y 1 , ... , X n ⊕ y n ) = L ( X 1 , ... , X n )y1,…,yn L(X1⊕y1,…,Xn⊕yn)=L(X1,…,Xn)
Si son dos secuencias pseudoaleatorias independientes, es un bit aleatorio independiente y , luego .X0→,X1→ T∈{0,1} Z⃗ =XT→ L(Z⃗ )≥min(X0→,X1→)
La primera propiedad significa que la medida es invariante al voltear el bit . La segunda propiedad significa que si mezclamos dos distribuciones , entonces el resultado es al menos tan bueno como el peor.i X⃗ ,Y⃗
Cualquier medida de aleatoriedad razonable satisfará la primera propiedad. La segunda propiedad se satisface con las medidas más populares, como entropía y min-entropía .H H∞
Ahora podemos establecer y probar un teorema que muestra que XORing dos secuencias pseudoaleatorias siempre es una buena idea.
Teorema. Sea dos secuencias pseudoaleatorias independientes de la misma longitud, y sea una medida de aleatoriedad admisible (una que cumpla las dos condiciones anteriores). Entonces LL( → X ⊕ → Y )≥max(L(X),L(Y)).X⃗ ,Y⃗ L
Prueba. Supongamos que . Entonces es una mezcla de las distribuciones de , mezclado de acuerdo con la distribución de . Como y una mezcla es al menos tan buena como la peor distribución que se está mezclando, obtenemos . X ⊕ Y X ⊕ y Y L ( X ⊕ y ) = L ( X ) L ( X ⊕ Y ) ≥ L ( X ) ◻L(X)≥L(Y) X⊕Y X⊕y Y L(X⊕y)=L(X) L(X⊕Y)≥L(X) □
Lo que este teorema significa es que si XOR dos secuencias pseudoaleatorias generadas usando dos claves independientes , el resultado siempre es al menos tan bueno como la mejor secuencia que se está XOR, con respecto a cualquier medida de aleatoriedad admisible.
En la práctica, para usar dos claves independientes, probablemente expandimos una clave a dos claves de manera pseudoaleatoria. Las dos claves no son independientes. Sin embargo, si utilizamos una forma "costosa" de expandir la clave única en dos claves, esperamos que las dos claves resultantes "parezcan" independientes, y así el teorema se mantenga "moralmente". En la criptografía teórica hay formas de hacer que esta afirmación sea precisa.
¿Deberíamos, entonces, XOR dos generadores de números pseudoaleatorios? Si no estamos restringidos por la velocidad, entonces esa es ciertamente una buena idea. Pero en la práctica tenemos un límite de velocidad. Entonces podemos hacer la siguiente pregunta. Supongamos que se nos dan dos PRNG, cada uno con un parámetro que controla el tiempo de funcionamiento (y, por lo tanto, la fuerza) del generador. Por ejemplo, podría ser la longitud de un LFSR o el número de rondas. Supongamos que usamos un PRNG con el parámetro , el otro con el parámetro y XOR el resultado. Podemos suponer que , de modo que el tiempo total de ejecución es constante. ¿Cuál es la mejor opción deT T T1 T2 T1+T2=t T1,T2 ? Aquí hay una compensación que es difícil de responder en general. Puede ser que el ajuste sea mucho peor que o .(t/2,t/2) (t,0) (0,t)
El mejor consejo aquí es apegarse a un PRNG popular que se considera fuerte. Si puede dedicar más tiempo a generar su secuencia, haga XOR de varias copias, usando claves independientes (o claves generadas al expandir una sola clave usando un PRNG costoso).
fuente
Le daré una oportunidad a esto, ya que estoy suficientemente perturbado por el consejo dado en algunas de las otras respuestas.
Deje que sean secuencias de bits infinitas generadas por dos RNG (no necesariamente PRNG que son deterministas una vez que se conoce el estado inicial), y estamos considerando la posibilidad de usar la secuencia con la esperanza de mejorar el comportamiento en algún sentido. Hay muchas formas diferentes en que podría considerarse mejor o peor en comparación con cada uno de y ; Aquí hay un pequeño puñado que creo que es significativo, útil y consistente con el uso normal de las palabras "mejor" y "peor":X⃗ ,Y⃗ X⃗ ⊕Y⃗ X⃗ ⊕Y⃗ X⃗ Y⃗
Primero pensemos en (0), que es el único de los tres que tiene alguna esperanza de ser preciso. Tenga en cuenta que si, de hecho, cualquiera de los dos RNG de entrada es realmente aleatorio, imparcial e independiente del otro, entonces el resultado XOR será realmente aleatorio e imparcial también. Con eso en mente, considere el caso cuando cree que son flujos de bits aislados verdaderamente aleatorios e imparciales, pero no está completamente seguro. Si son las probabilidades respectivas de que esté equivocado acerca de cada uno de ellos, entonces la probabilidad de que no sea realmente aleatorio es entonces , de hecho mucho menos desdeX⃗ ,Y⃗ εX,εY X⃗ ⊕Y⃗ ≤εXεY<min{εX,εY} εX,εY Se supone que están muy cerca de 0 ("usted cree que son verdaderamente aleatorios"). Y, de hecho, es incluso mejor que eso, cuando también tenemos en cuenta la posibilidad de que sea verdaderamente independiente, incluso cuando ninguno de los dos sea verdaderamente aleatorio:
Por lo tanto, podemos concluir que en el sentido (0), XOR no puede hacer daño, y podría ayudar mucho.X⃗ ,Y⃗
Sin embargo, (0) no es interesante para los PRNG, ya que en el caso de los PRNG ninguna de las secuencias en cuestión tiene ninguna posibilidad de ser realmente aleatoria.
Por lo tanto, para esta pregunta, que de hecho se trata de PRNG, debemos estar hablando de algo como (1) o (2). Dado que se trata de propiedades y cantidades como "observable", "grave", "obvio", "aparente", ahora estamos hablando de la complejidad de Kolmogorov, y no voy a tratar de precisar eso. Pero iré tan lejos como para hacer la afirmación esperanzadora de que, según tal medida, "01100110 ..." (período = 4) es peor que "01010101 ..." (período = 2) que es peor que " 00000000 ... "(constante).
Ahora, uno podría adivinar que (1) y (2) seguirán la misma tendencia que (0), y que por lo tanto, la conclusión "XOR no puede doler" aún podría mantenerse. Sin embargo, tenga en cuenta la posibilidad significativa de que ni ni fueran observablemente no aleatorios, sino que las correlaciones entre ellos hacen que sea observablemente no aleatorio. El caso más grave de esto, por supuesto, es cuando (o ), en cuyo caso es constante, el peor de todos los resultados posibles; en general, es fácil ver que, independientemente de lo buenos que sean y ,X⃗ Y⃗ X⃗ ⊕Y⃗ X⃗ =Y⃗ X⃗ =not(Y⃗ ) X⃗ ⊕Y⃗ X⃗ Y⃗ X⃗ y necesitan estar "cerca" de ser independientes para que su xor sea no observable-no aleatorio. De hecho, ser dependiente no observable puede definirse razonablemente como siendo no observable-no aleatorio.Y⃗ X⃗ ⊕Y⃗
Tal dependencia sorpresa resulta ser un gran problema.
Un ejemplo de lo que sale mal
La pregunta dice "Estoy excluyendo el ejemplo común de varios registros de desplazamiento de retroalimentación lineal que trabajan juntos ya que son de la misma familia". Pero voy a excluir esa exclusión por el momento, para dar un ejemplo muy simple y claro de la vida real del tipo de cosas que pueden salir mal con XORing.
Mi ejemplo será una implementación antigua de rand () que estaba en alguna versión de Unix alrededor de 1983. IIRC, esta implementación de la función rand () tenía las siguientes propiedades:
No he podido localizar el código fuente original, pero supongo que al juntar un par de publicaciones en https://groups.google.com/forum/#!topic/comp.os.vms/9k4W6KrRV3A que hizo precisamente lo siguiente (código C), que concuerda con mi memoria de las propiedades anteriores:
Como uno podría imaginar, tratar de usar este rand () de varias maneras condujo a una variedad de decepciones.
Por ejemplo, en un momento intenté simular una secuencia de lanzamientos aleatorios de monedas al tomar repetidamente:
es decir, el bit menos significativo. El resultado fue una simple alternancia cabeza-cruz-cabeza-cruz. Al principio fue difícil de creer (¡debe ser un error en mi programa!), Pero después de convencerme de que era cierto, intenté usar el siguiente bit menos significativo. Eso no es mucho mejor, como se señaló anteriormente: ese bit es periódico con el período 4. Continuar explorando bits sucesivamente más altos reveló el patrón que noté anteriormente: es decir, cada siguiente bit de orden superior tenía el doble del período del anterior, así que en A este respecto, el bit de orden superior fue el más útil de todos. Sin embargo, tenga en cuenta que aquí no había un umbral en blanco y negro "el bit es útil, el bit no es útil"; todo lo que realmente podemos decir es que las posiciones de bits numeradas tenían diversos grados de utilidad / inutilidad.i i−1
También probé cosas como codificar aún más los resultados o XORing juntos los valores devueltos de múltiples llamadas a rand (). XORing pares de valores sucesivos de rand () fue un desastre, por supuesto, ¡resultó en todos los números impares! Para mis propósitos (es decir, producir una secuencia "aparentemente aleatoria" de lanzamientos de monedas), el resultado de paridad constante del XOR fue incluso peor que el comportamiento alterno par-impar del original.
Una ligera variación pone esto en el marco original: es decir, que sea la secuencia de valores de 15 bits devueltos por rand () con una semilla dada , y la secuencia de una semilla diferente . Nuevamente, será una secuencia de números pares o impares, que es peor que el comportamiento alternativo par / impar original.X⃗ sX Y⃗ sY X⃗ ⊕Y⃗
En otras palabras, este es un ejemplo donde XOR empeoró las cosas en el sentido de (1) y (2), por cualquier interpretación razonable. También es peor en otras formas:
Ninguno de (3), (4), (5) es obvio, pero todos son fácilmente verificables.
Finalmente, consideremos reintroducir la prohibición de los PRNG de la misma familia. El problema aquí, creo, es que nunca está realmente claro si dos PRNG son "de la misma familia", hasta que / a menos que alguien comience a usar el XOR y se dé cuenta (o un atacante) que las cosas empeoraron en el sentido de (1) y (2), es decir, hasta que los patrones no aleatorios en la salida crucen el umbral de no notado a notado / vergonzoso / desastroso, y en ese punto es demasiado tarde.
Estoy alarmado por otras respuestas aquí que dan consejos no calificados "XOR no puede hacer daño" sobre la base de medidas teóricas que me parecen hacer un mal trabajo de modelar lo que la mayoría de la gente considera "bueno" y "malo" sobre PRNG en la vida real. Ese consejo se contradice con ejemplos claros y descarados en los que XOR empeora las cosas, como el ejemplo de rand () dado anteriormente. Si bien es concebible que los PRNG relativamente "fuertes" puedan mostrar consistentemente el comportamiento opuesto cuando XOR se acerca al del PRNG de juguete que era rand (), lo que hace que XOR sea una buena idea para ellos, no he visto evidencia en esa dirección, teórica o empírica, por lo que me parece irrazonable suponer que eso sucede.
Personalmente, habiendo sido mordido por sorpresa por XORing rand () s en mi juventud, y por innumerables otras correlaciones sorpresa variadas a lo largo de mi vida, tengo pocas razones para pensar que el resultado será diferente si vuelvo a intentar tácticas similares. Es por eso que yo, personalmente, sería muy reacio a XOR juntos múltiples PRNG a menos que se hayan realizado análisis y análisis exhaustivos para darme cierta confianza de que podría ser seguro hacerlo para los RNG en cuestión. Como una posible cura para cuando tengo poca confianza en uno o más de los PRNG individuales, es poco probable que XORing aumente mi confianza, por lo que es poco probable que lo use para tal fin. Me imagino que la respuesta a su pregunta es que este es un sentimiento muy extendido.
fuente
DESCARGO DE RESPONSABILIDAD: Esta respuesta es estrictamente sobre "No lo estamos haciendo" y no "aquí hay una prueba matemática de por qué puede o no puede funcionar". No pretendo que XOR introduzca (o no) ninguna vulnerabilidad criptográfica. Mi punto es solo que la experiencia nos muestra que incluso los esquemas más simples casi siempre introducen consecuencias imprevistas, y es por eso que los evitamos.
La "aleatoriedad" es solo una punta del iceberg cuando se trata de RNG y PRNG. Hay otras cualidades que son importantes, por ejemplo, la uniformidad.
Imagine un dado común que es bastante bueno RNG por sí mismo. Pero ahora supongamos que necesita un rango de 1-5 en lugar de 1-6. Lo primero que viene a la mente es simplemente borrar la cara 6 y reemplazarla con un extra 1. La "aleatoriedad" permanece (los resultados aún son verdaderamente aleatorios), sin embargo, la uniformidad sufre mucho: ahora 1 es dos veces más probable que otros resultados.
La combinación de resultados de múltiples RNG es una pendiente resbaladiza similar. P.ej. La simple adición de 2 lanzamientos de dados elimina por completo cualquier uniformidad, ya que "7" ahora es 6 veces más probable que "2" o "12". Estoy de acuerdo en que XOR se ve mejor que la adición a primera vista, pero en PRNG nada resulta como se ve a primera vista.
Es por eso que tendemos a apegarnos a implementaciones conocidas, porque alguien gastó mucho tiempo y dinero en investigarlas y todas las deficiencias son bien conocidas, entendidas y pueden solucionarse. Cuando despliegas la tuya, potencialmente creas vulnerabilidades y debes hacer un esfuerzo similar para probarlo. Como muestra el ejemplo de adición de dados, combinar no puede ser muy diferente de crear uno nuevo desde cero.
La seguridad es una cadena, tan fuerte como su componente más débil. Una regla de oro en seguridad: cada vez que combinas 2 cosas, generalmente obtienes una suma de defectos, no una suma de fortalezas.
fuente