Il n'y a en fait rien de mal avec votre première requête, syntaxiquement c'est parfait comme le montre cet exemple travaillé.
mysql> SET @@SESSION.block_encryption_mode = 'aes-256-cbc';
mysql> create table MyTable(
-> Encrypted_ID varbinary(256),
-> InitializationVector_iv varbinary(16)
-> );
Query OK, 0 rows affected (0.93 sec)
mysql> SET @iv = RANDOM_BYTES(16);
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO MyTable SET Encrypted_ID = AES_ENCRYPT('hello','key', @iv), InitializationVector_iv = @iv;
Query OK, 1 row affected (0.17 sec)
mysql> SELECT CAST(AES_DECRYPT(Encrypted_ID,'key', InitializationVector_iv) AS CHAR) from MyTable;
+------------------------------------------------------------------------+
| CAST(AES_DECRYPT(Encrypted_ID,'key', InitializationVector_iv) AS CHAR) |
+------------------------------------------------------------------------+
| hello |
+------------------------------------------------------------------------+
1 row in set (0.00 sec)
Quant à savoir pourquoi cela ne fonctionne pas, j'ai réussi à obtenir que la requête renvoie NULL dans 2 scénarios. Premièrement, vous obtenez NULL retourné si vous utilisez un iv différent pour le cryptage et le décryptage, vous voudrez peut-être regarder comment vous stockez en tant que iv. Deuxièmement, vous obtenez NULL lorsque la variable block_encryption_mode est définie différemment lors du stockage et de la tentative de récupération de la valeur, vérifiez que vous ne revenez pas accidentellement à la valeur par défaut 'aes-128-ebc entre les sessions. Il peut y en avoir d'autres...
La deuxième requête échouera car vous devez fournir le iv aux fonctions de chiffrement et de déchiffrement, vous ne l'utilisez que pour chiffrer. De plus, puisque vous prenez les valeurs de MyTable, Encrypted_ID sera déjà crypté et l'effet de cette requête serait de le crypter à nouveau, avant d'inverser cela pour vous ramener à la valeur stockée (cryptée).
Enfin, AES n'utilisera que 16 octets du iv donc autant faire que VARBINARY(16).