En criptografía , el generador de contracción es una forma de generador de números pseudoaleatorios destinado a ser utilizado en un cifrado de flujo . Fue publicado en Crypto 1993 por Don Coppersmith , Hugo Krawczyk y Yishay Mansour. [1]
El generador de contracción utiliza dos registros de desplazamiento con retroalimentación lineal . Uno, llamado secuencia A , genera bits de salida, mientras que el otro, llamado secuencia S , controla su salida. Tanto A como S se sincronizan; si el bit S es 1, entonces se emite el bit A ; si el bit S es 0, se descarta el bit A , no se emite nada y los registros se sincronizan nuevamente. Esto tiene la desventaja de que la tasa de salida del generador varía de manera irregular y de una manera que insinúa el estado de S ; este problema se puede superar almacenando en búfer la salida. La secuencia aleatoria generada por LFSR no puede garantizar la imprevisibilidad en un sistema seguro y se han propuesto varios métodos para mejorar su aleatoriedad [2].
A pesar de esta simplicidad, actualmente no se conocen ataques mejores que la búsqueda exhaustiva cuando los polinomios de retroalimentación son secretos. Sin embargo, si se conocen los polinomios de retroalimentación, el ataque más conocido requiere menos de A • S bits de salida. [3]
Una variante es el generador autoencogible .
Este ejemplo utiliza dos LFRS de Galois para generar el flujo de bits pseudoaleatorio de salida. El código Python se puede utilizar para cifrar y descifrar un archivo o cualquier flujo de bytes.
#!/usr/bin/env python3importar sistema# ---------------------------------------------------------------------------- # Las funciones de Crypto4o comienzan aquí # ----------------------------------------------------------------------------clase GLFSR : """Registro de desplazamiento con retroalimentación lineal de Galois.""" def __init__ ( self , polynom , initial_value ): print "Usando el polinomio 0x %X , valor inicial: 0x %X ." % ( polynom , initial_value ) self . polynom = polinom | 1 self . data = valor_inicial tmp = polinom self . mask = 1 mientras tmp != 0 : si tmp y self . mask != 0 : tmp ^= self . mask si tmp == 0 : romper yo . máscara <<= 1 def next_state ( self ) : self.datos << = 1 valor de recuperación = 0 si self.data & self.mask ! = 0 : retval = 1 self.data ^ = self.polynom devolución de devoluciónclase SPRNG : def __init__ ( self , polinomio_d , valor_inicio_d , polinomio_c , valor_inicio_c ): imprimir " GLFSR D0:" , self.glfsr_d = GLFSR ( polinomio_d , valor_inicio_d ) imprimir " GLFSR C0: " , self.glfsr_c = GLFSR ( polinomio_c , valor_inicio_c ) def next_byte ( auto ): byte = 0 bitpos = 7 mientras sea verdadero : bit_d = self.glfsr_d.next_state ( ) bit_c = self.glfsr_c.next_state ( ) si bit_c != 0 : bit_r = bit_d byte |= bit_r << bitpos posición de bits -= 1 si bitpos < 0 : romper byte de retorno# ------------------------------------------------------------------------ # Las funciones de Crypto4o terminan aquí # ------------------------------------------------------------------------def principal ( ) : prng = SPRNG ( int ( sys.argv [ 3 ], 16 ), int ( sys.argv [ 4 ] , 16 ) , int ( sys.argv [ 5 ] , 16 ) , int ( sys.argv [ 6 ] , 16 ) , ) con abierto ( sys . argv [ 1 ], "rb" ) como f , abierto ( sys . argv [ 2 ], "wb" ) como g : mientras sea verdadero : input_ch = f . read ( 1 ) si input_ch == "" : romper canal_aleatorio = prng.next_byte ( ) y 0xFF g.write ( chr ( ord ( entrada_canal ) ^ canal_aleatorio ) ) si __nombre__ == "__principal__" : principal ()