Вопрос о том, как правильно шифровать данные и хранить их на SQL сервере, является одним из наиболее часто задаваемых клиентами вопросов. Одна из основных проблем, которую я вижу в этой области — это хранение закрытых данных на SQL сервере в открытом виде.
Например, если пароль хранится на SQL сервере в незашифрованном виде, то злоумышленик может легко прочесть все пароли с помощью обычного SELECT запроса. Вы можете разработать ваш собственный способ для шифрования паролей, а в данной статье мы обсудим методы, которые уже встроены в SQL сервер.
Начиная с SQL сервера версии 6.x, для шифрования данных вы можете применять функцию ENCRYPT, которая использует тот же метод (шифрования), что и опция WITH ENCRYPTION. Это достаточно обьемная проблема, которую мы обсудим после следующего примера. При использовании функции ENCRYPT размещайте ее впереди строчной переменной, как указано ниже: SELECT ENCRYPT(‘TestPW1’)
В результате получим:
——————————
0x5400650073007400500057003100
(1 row(s) affected)
Давайте пойдем дальше и проверим как эта функция работает. Создаем тестовую таблицу и загружаем в нее исходные данные, как указано ниже: CREATE TABLE Users ( UserID Varchar(10), UserPW Varchar (20))
INSERT INTO Users values('TestUser1',ENCRYPT('TestPW1'))
INSERT INTO Users values('TestUser2',ENCRYPT('TestPW2'))
INSERT INTO Users values('TestUser3',ENCRYPT('TestPW3'))
INSERT INTO Users values('TestUser4',ENCRYPT('TestPW4'))
Если вы теперь выполните выборку данных из этой таблицы, то результат будет представлен в зашифрованном виде. Обратите внимание на то, что результаты выполнения SELECT ENCRYPT(‘TestPW1’) отличаются от результатов выборки данных из таблицы Users после ее заполнения. Алгоритм, который SQL сервер использует для шифрования данных, является относительно простым и различает регистр до тех пор, пока он не сохранен в таблице. После этого он становится очень сложным для расшифровки. Возможность сохранить данные в зашифрованном поле может использоваться для хранения паролей. Вы не можете расшифровать обратно данные, которые уже зашифрованы и сохранены в таблице. Единственное, что вы можете сделать, так это сравнить данные, как указано ниже: SELECT * from Users where UserID = ‘TestUser2’ and UserPW = ENCRYPT(‘TestPW2’)
Не забудьте, что вышеуказанная функция работает с учетом регистра. Если вы предпочитаете не использовать регистр, то лучше сохранять все данные в верхнем регистре используя функцию UPPER. Функцию UPPER необходимо будет использовать как в INSERT выражении, так и в SELECT выражении, которые упоминались выше. Например, выражение INSERT должно будет выглядеть следующим образом: INSERT INTO USERS values(‘TestUser1’,ENCRYPT(UPPER(‘TestPW1’)))
SELECT * from Users where UserID = 'TestUser2'
and UserPW = ENCRYPT(UPPER('TestPW2'))
Обратите также внимание, что когда вы просматриваете данные в вышеизложенном примере, то их видимая длина отличается от действительной, что является признаком хорошо зашифрованных данных. UserID UserPW ———- ——————— TestUser1 T TestUser2 T TestUser3 T TestUser4 T
Но в действительности, если вы проверите длину поля с использованием функции LEN, то вы получите фактическую длину поля. userid Length ———- ———— TestUser1 14 TestUser2 14 TestUser3 14 TestUser4 14
Этот результат удостоверяет, что длина поля отражает длину уже зашифрованных данных, а не длину исходных данных. А теперь (поговорим) о больших недостатках, упоминавшихся ранее. Эта хранимая процедура не поддерживается Microsoft и может быть легко изменена или изьята. Хорошим примером явилось изменение этой функции между версиями SQL сервер 6.5 и 7.0. Другим важным вопросом является дешифрование. Очевидно, Microsoft не делает это просто и зашифрованные данные могут быть легко расшифрованы только с использованием метода сравнения, который я показывал ранее.
Если вы не хотите использовать этот метод для шифрования ваших паролей, то существуют другие, более совершенные. Эти методы являются более устойчивыми и более защищенными чем тот, который мы обсуждали. Например, Les Smith опубликовал две статьи, в которых показано как использовать Java или COM для шифрования паролей. Их можно найти по адресу:
http://www.sqlservercentral.com/columnists/lsmith/usingjavatoencryptpasswords.asp
Если защищенность ваших данных является действительно важной, то функция ENCRYPT — это совсем не то, что вам нужно. Вместо нее лучше использовать один из нескольких уже реализованных методов, о которых Les Smith упоминает в своих статьях. Эти методы шифрования не будут изменяться от версии к версии, но требуют немного больше работы.