Właściwie nie ma nic złego w pierwszym zapytaniu, składniowo jest na miejscu, jak pokazuje ten działający przykład.
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)
Jeśli chodzi o to, dlaczego to nie działa, udało mi się uzyskać zapytanie zwracające NULL w 2 scenariuszach. Po pierwsze, otrzymasz NULL zwrócone, jeśli używasz innego iv do szyfrowania i deszyfrowania, więc możesz chcieć przyjrzeć się, jak przechowujesz jako iv. Po drugie, otrzymujesz NULL, gdy masz zmienną block_encryption_mode ustawioną inaczej podczas przechowywania i próby pobrania wartości, sprawdź, czy przypadkowo nie powracasz do domyślnego „aes-128-ebc” między sesjami. Mogą być inne...
Drugie zapytanie zakończy się niepowodzeniem, ponieważ musisz podać iv zarówno do funkcji szyfrowania, jak i deszyfrowania, używasz go tylko do szyfrowania. Ponadto, ponieważ pobierasz wartości z MyTable, Encrypted_ID będzie już zaszyfrowany, a efektem tego zapytania będzie ponowne zaszyfrowanie, przed cofnięciem tego, aby wrócić do zapisanej (zaszyfrowanej) wartości.
Wreszcie, AES będzie używał tylko 16 bajty iv, więc równie dobrze możesz zrobić to VARBINARY(16).