¿Por qué diferentes implementaciones de AES producen diferentes resultados?

Siento que entiendo bastante bien las funciones hash y los contratos que conllevan.

SHA1 en la entrada X SIEMPRE producirá la misma salida. Puede usar una biblioteca de Python, una biblioteca de Java o lápiz y papel. Es una función, es determinista. Mi SHA1 hace lo mismo que el tuyo y el de Alice y Bob.

Según tengo entendido, AES también es una función. Pones algunos valores, escupe el texto cifrado.

¿Por qué, entonces, podría haber temor de que Truecrypt (por ejemplo) esté "roto"? No están diciendo que AES está roto, están diciendo que el programa que lo implementa puede estarlo. AES es, en teoría, sólido. Entonces, ¿por qué no puede simplemente ejecutar un archivo a través de Truecrypt, ejecutarlo a través de una función de "AES de referencia" y verificar que los resultados sean los mismos? Sé que absolutamente no funciona así, pero no sé por qué.

¿Qué hace a AES diferente de SHA1 de esta manera? ¿Por qué podría Truecrypt AES escupir un archivo diferente que Schneier-Ifier * AES, cuando ambos recibieron las mismas entradas?

Al final, mi pregunta se reduce a:

My_SHA1 (X) == Bobs_SHA1 (X) == ... etc.

Pero TrueCrypt_AES (X)! = HyperCrypt_AES (X)! = VeraCrypt_AES (X) etc. ¿Por qué es eso? ¿Todos esos programas envuelven AES, pero tienen diferentes formas de determinar cosas como un vector de inicialización o algo así?

* este sería el nombre de mi programa de cifrado de archivos si alguna vez escribiera uno

Respuestas a la pregunta(2)

Su respuesta a la pregunta