Entiendo que un IV (vector de inicialización) debe ser único e impredecible, pero he encontrado poca orientación en cuanto a lo que es más importante.
Para un cifrado AES tengo un tamaño de bloque de 128 bits para usar. Estaba considerando el siguiente esquema:
Bits 0 a 39: 40 bits menos significativos de milisegundos desde la época. Esto se repite aproximadamente una vez cada 34 años. Un período de tiempo que probablemente exceda el tiempo durante el cual los cifrados actuales se considerarán seguros y, por lo tanto, únicos dentro de la vida útil de los datos cifrados.
Bits 40 a 63: un contador de 24 bits que comienza en un valor aleatorio y se incrementa por cada IV. Para garantizar la exclusividad, solo un subproceso de ejecución puede acceder al contador a la vez y, por lo tanto, el número máximo de accesos por milisegundo está limitado por la velocidad de reloj de una sola CPU. Esta aplicación se utilizará en las CPU normales en las que las velocidades de reloj actualmente se encuentran en un nivel bastante inferior a la velocidad de 16 GHz que tomaría agotar este contador en 1 milisegundo.
Bits 64 a 95: He concatenado información sobre el hardware y el proceso y luego utilicé un SHA-256 con estos datos. Estoy utilizando los primeros 32 bits del hash resultante como una forma de identificar de forma única el proceso de origen. Esto reduce la posibilidad de que 2 procesos en diferentes servidores puedan generar el mismo IV. La paradoja del cumpleaños sugiere que si tengo 65000 procesos simultáneos, hay una probabilidad 0.5 de que dos de ellos compartan los mismos 32 bits aquí, pero con mi máximo previsto de 1000 procesos, la probabilidad es inferior a 0.00001.
Bits de 96 a 127: 32 bits aleatorios extraídos de un generador de números aleatorios seguro.
Este IV se transmitiría junto con el texto cifrado.
Mi primera pregunta: ¿es este esquema razonable para usar con los modos de cifrado de bloque: CBC, PCBC, CFB, OFB y CTR?
Mi segunda pregunta: ¿hay alguna ventaja al pasar los 128 bits a través de MD5 antes de usarlos? Esto sería "mejorar" el IV al entrelazar las partes fijas y variables de la entrada.
Mi tercera pregunta: por desgracia, también tengo que admitir cifrados de bloque de 64 bits como DES, DESede y Blowfish. No creo que ningún usuario realmente utilice tales cifrados, pero tienen que ser soportados. Tales cifrados requieren un mero 64 bit IV. No veo nada de lo anterior que pueda eliminar razonablemente mientras ofrezco garantías razonables de no repetibilidad y no previsibilidad. ¿Qué se puede hacer? Todo lo que puedo pensar en hacer es tomar los primeros 64 bits de un hash seguro. ¿Eso es suficiente?
Mi cuarta pregunta: solo para CBC, PCBC y CFB, si uso los primeros 64 bits como un verdadero IV, y luego introduzco los segundos 64 bits en el cifrado como si fueran el primer bloque del mensaje pero descartando el salida: ¿funciona así como el uso de un IV de 128 bits a pesar de que el tamaño del bloque del cifrado es de solo 64 bits?
Como un punto adicional, los 32 bits iniciales del texto sin formato de algunas decenas de mensajes podrían ser conocidos por un atacante. No podrían controlar los IV generados para esos mensajes, pero podrían identificarlos por otros medios dentro de unas decenas de miles de mensajes. El principal requisito de este sistema de cifrado es evitar que un ataque con dicha información acceda a cualquier parte del texto sin formato de cualquier otro mensaje. Si el esquema IV o los modos de bloque de cifrado que he mencionado serían débiles en tales circunstancias, agradecería que la gente lo señalara.