ВАЖНОЕ ПРИМЕЧАНИЕ: Я не криптограф. Я не рекомендую этот подход для обеспечения безопасности ваших данных путем «шифрования» этого способом.
Что касается обновления строки, вы можете использовать отклонение MySQL от («расширение до?») Из стандарта SQL.
С заявлением, как это:
UPDATE mytable
SET col1 = 'foo'
, col2 = col1
col1
и col2
в конечном итоге с тем же значением, 'foo'
, поскольку ссылка на col1
во втором назначении возвращает значение, которое было только что назначенный col1
(предыдущий Назначение. Приказ важен здесь!)
Я думаю, что функция MySQL AES_ENCRYPT
принимает два аргумента, а не три, поэтому я немного смущен примером, который вы показываете.
В качестве примера подхода к обновлению (откладывая на мгновение, как бы вы заменить @RANDOM_BYTES с чем-то, что получает вам значение, которое вы можете использовать):
UPDATE employee
SET random_bytes = @RANDOM_BYTES
, encrypted_name = AES_ENCRYPT(name,random_bytes)
я настоятельно рекомендую вам проверить это , и убедитесь, что он делает то, что вы хотите, на тестовые данные в тестовой среде, прежде чем полагаться на него в какой-то важности.
Убедитесь, что столбец encrypted_name
определен как «двоичный» тип, например. VARBINARY
(достаточной длины для хранения зашифрованного/дополненного значения) или BLOB
.Либо это, либо вам нужно будет закодировать двоичное значение, используя, например, кодировку HEX или base64, чтобы ее можно было сохранить в столбце символов.
Что касается возврата значения вместо @RANDOM_BYTES
, это будет выглядеть немного сложнее.
Мы можем использовать повторные вызовы для RAND()
, чтобы возвращать псевдослучайные значения, но мы должны получить это в 128-битовое двоичное значение или любую длину ключа, необходимую для AES_ENCRYPT
.
Я размышляю вслух здесь ...
FLOOR(RAND()*256.0)
получит нам целое значение от 0 до 255, что было бы достаточно для случайного байта.
Функция MD5()
вернет нам 128-битное значение (16 байт), представленное в 32 шестнадцатеричных цифрах.
Функция SHA2()
возвращает значения, превышающие эти значения, мы можем, конечно, обрезать их до любой необходимой длины.
Трюк будет получать достаточную случайность в этих хеш-функциях, я думаю, что одно значение поплавка не будет достаточным количеством случайности. Мы могли бы использовать некоторые другие значения из строки в качестве «соли» в сочетании с некоторыми случайными байтами.
Нам нужно быть осторожным, какие функции возвращают шестнадцатеричные символьные строки и которые возвращают BINARY.
Мы могли бы получить два псевдослучайных двоичных байт, как это:
CHAR(FLOOR(RAND()*256*256) USING BINARY)
Если мы конкатенации восемь повторений, что вместе, что бы получить нас 16 байт двоичных данных. Мы можем получить немного меньше хаотичность, порождая 4 байта, в то время, и конкатенации серию из четырех из них:
CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
Я думаю, что-то вроде этого, хотя мы определенно хотим, чтобы проверить, что выражение, предназначенное для возврата случайное 16-байтовое двоичное значение
random_binary VARBINARY(16)
UPDATE employee
SET random_bytes = -- 16-byte pseudo-random binary string
CONCAT(CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
, CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
, CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
, CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
)
, encrypted_name = AES_ENCRYPT(name,random_bytes)
При таком подходе, крайне важно, чтобы random_bytes столбец быть определен «двоичный» тип, например, VARBINARY(16)
.
Кроме того, значение, хранящееся в encrypted_name
, будет бинарным, поэтому его необходимо также определить как BINARY ... шифрование AES добавляет дополнение (для этого есть формула, которая зависит от длины ключа ... столбец, безусловно, должен быть длиннее, чем имя.
Если мы считаем, что хранение BINARY может представлять проблему где-то на этом пути, например, при переводе символов, которое будет применено позднее, мы можем закодировать двоичный код как шестнадцатеричные цифры и сохранить это
random_hex VARCHAR(32)
UPDATE employee
SET random_hex = -- 16-byte pseudo-random binary as 32 hex digits
HEX(
CONCAT(CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
, CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
, CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
, CHAR(FLOOR(RAND()256*256*256*256) USING BINARY)
)
)
, encrypted_name_hex = HEX(AES_ENCRYPT(name,UNHEX(random_bytes)))
ПРИМЕЧАНИЕ. Я не уверен, что AES_ENCRYPT возвращает двоичный или шестнадцатеричный код, который может зависеть от версии MySQL, которую вы используете. Я также не уверен в длине ключа.
Более длинная длина ключа была бы «более безопасной», чем более короткая, но это зависит от алгоритма шифрования. Кроме того, функция RAND()
не «по-настоящему» случайна ...
Я думаю, что гораздо более серьезная проблема связана с сохранением ключа дешифрования в той же строке с зашифрованным значением. Зашифрованное значение защищено только в том случае, если ключ защищен.
Это не очень понятно для меня. MYSQL уже имеет случайную функцию байтов, как вы заметили в своем запросе. Если вы хотите обновить всю таблицу, то вы можете просто выполнить цикл и иметь переменную в локальной области внутри цикла, а затем вызвать эту переменную. – Hozikimaru
Прости, я уточнил. –
Последние два предложения в моем (мучительно длинном) ответе должны быть в самом верху моего ответа, я повторю эти два предложения здесь. «Я думаю, что гораздо более серьезная проблема заключается в сохранении ключа дешифрования в * той же строке * с зашифрованным значением. Зашифрованное значение защищено только в том случае, если ключ защищен» – spencer7593