2015-05-27 3 views
0

Мне нужно обновить и зашифровать таблицу (всю таблицу) без использования хранимой процедуры. Для шифрования требуются как ключ, так и случайный массив массивов. случайная байтовый массив будет сохранен в той же таблицеУстановить одно и то же случайное значение дважды в одном запросе для шифрования в MySql

update employee set name = aes_encrypt(name,'key',@RANDOM_BYTES), random_bytes = @RANDOM_BYTES; 

первый и второй @RANDOM_BYTES должны совпадать. поэтому мы шифруем значение и сохраняем случайное значение в той же таблице для дешифрования позже.

Интересно, возможно ли это вообще.

Я могу использовать несколько запросов, но не хранимые процедуры.

+0

Это не очень понятно для меня. MYSQL уже имеет случайную функцию байтов, как вы заметили в своем запросе. Если вы хотите обновить всю таблицу, то вы можете просто выполнить цикл и иметь переменную в локальной области внутри цикла, а затем вызвать эту переменную. – Hozikimaru

+0

Прости, я уточнил. –

+0

Последние два предложения в моем (мучительно длинном) ответе должны быть в самом верху моего ответа, я повторю эти два предложения здесь. «Я думаю, что гораздо более серьезная проблема заключается в сохранении ключа дешифрования в * той же строке * с зашифрованным значением. Зашифрованное значение защищено только в том случае, если ключ защищен» – spencer7593

ответ

2

Я не 100% абсолютно, абсолютно уверен, но я абсолютно уверен, что MySQL оценивает НАБОРЫ слева направо, так что небольшое изменение должно работать:

UPDATE employee 
SET random_bytes = @RANDOM_BYTES 
    , name = aes_encrypt(name,'key',random_bytes) 
; 

Edit: Вы можете использовать этот аспект делать вещи, такие как swap целочисленные значения между двумя столбцами в одной строке (хотя, очевидно, SET для этого намного сложнее.)

+0

работает, можете ли вы взглянуть на http: // stackoverflow.com/questions/30494034/replace-temp-column-with-variable-in-an-update-mysql-query –

+0

@Uueerdo: (Я только что опубликовал ответ, я начал отвечать на него, отвлекся на что-то большее срочно.) Я думал, что вопрос был более активным, чем просто это. Ваш ответ на 100% абсолютно правильный * для * MySQL. Эта «функция» MySQL - это отклонение от («улучшения до?») Стандарта SQL. В стандарте SQL говорится, что вторая ссылка на 'random_bytes' должна возвращать значение, которое было в строке, прежде чем оно было изменено оператором. (Я знаю 100% за то, что это не работает с Oracle.) – spencer7593

+0

@ spencer7593 Да, мой опыт в основном связан с MySQL, я бы не стал доверять этому, чтобы работать в другом месте, но это заставляет меня задуматься. В заданном вопросе не было сохранено procs, но если TRIGGER были опцией, проблема могла быть решена просто путем запуска триггера по фактическому расшифровке/повторному шифрованию всякий раз, когда было изменено поле ключа. – Uueerdo

0

Вы можете использовать курсоры для прокрутки каждой строки. См. https://dev.mysql.com/doc/refman/5.0/en/cursors.html

и все, что вам нужно сделать, это просто определить переменную внутри области цикла, таким образом она будет сгенерирована один раз.

SET Bytes = @RANDOM_BYTES 

С этого момента вы можете просто обновить всю таблицу теми же случайными байтами для обоих столбцов.

0

ВАЖНОЕ ПРИМЕЧАНИЕ: Я не криптограф. Я не рекомендую этот подход для обеспечения безопасности ваших данных путем «шифрования» этого способом.

Что касается обновления строки, вы можете использовать отклонение 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() не «по-настоящему» случайна ...

Я думаю, что гораздо более серьезная проблема связана с сохранением ключа дешифрования в той же строке с зашифрованным значением. Зашифрованное значение защищено только в том случае, если ключ защищен.

+0

* DOH! * С MySQL 5.6.x была введена функция «RANDOM_BYTES». Жестко сложные выражения в этом ответе были бы подходящей (?) Эмуляцией RANDOM_BYTES в более ранних версиях MySQL, 5.1 и 5.5. (Вероятно, это были выражения, похожие на те, что были в этом ответе, что привело к внедрению функции «RANDOM_BYTES». – spencer7593

Смежные вопросы