很多时候,我们的数据库表中会存储很多敏感信息,如用户的手机号、身份证号、密码之类的,这些数据如果不做好加密的话,一旦数据泄漏就会导致重要信息泄露。
一般来说都需要对敏感字段进行加密,然后再在数据库中保存加密后的数据,这样即使被拖库也没关系,比如攻击者拿到的只是加密后的密码,并不知道真实密码是什么。
那么,我们应该如何做数据库的加密呢。通常来说有以下几种办法:
服务端加解密指的就是数据库在存入数据库之前就加密好,然后再从数据库取出之后进行解密。这样可以保证数据库的数据绝对安全,因为数据库也不知道明文到底是什么。
一般来说我们可以选择各种各样的加密算法,如对称加密和非对称加密都可以,一般来说用对称加密就行了。
当然,有些场景下也可以用MD5(MD5严格来说并不是加密算法,只是一种hash算法),但是需要注意的是MD5不支持解密,所以只能用于那种存储后只做匹配而不作查询展示的场景,如用户的密码。而需要展示的场景,如手机号等就需要支持解密。
MySQL提供了一些内置的加密函数,我们可以直接使用这些加密函数进行数据加密:
-- 加密数据
INSERT INTO user_data (username, credit_card) VALUES ('Hollis', AES_ENCRYPT('1234-5678-9012-3456', 'hollis_secret_key'));
-- 解密数据
SELECT username, AES_DECRYPT(credit_card, 'hollis_secret_key') FROM user_data WHERE username = 'John';
-- 使用随机盐加密密码
INSERT INTO user_credentials (username, password_hash) VALUES ('Hollis', ENCRYPT('my_password', 'ab'));
-- 验证密码
SELECT * FROM user_credentials WHERE username = 'Hollis' AND password_hash = ENCRYPT('entered_password', password_hash);
-- 存储MD5哈希值
INSERT INTO user_data (username, password_hash) VALUES ('Hollis', MD5('hollis666'));
-- 验证密码
SELECT * FROM user_data WHERE username = 'Hollis' AND password_hash = MD5('hollis666');
-- 存储MySQL原生密码散列
INSERT INTO mysql_users (username, password_hash) VALUES ('Hollis', PASSWORD('hollis666'));
MySQL 5.7开始,InnoDB支持对静态数据加密。适用于按表的文件表空间、常规表空间、mysql系统表空间、redolog和undolog进行加密。
从MySQL 8.0.16开始,还支持为schema和常规表空间设置默认加密,这允许DBA控制是否对在这些schema和表空间中创建的表进行加密。
关于表空间的加密,大家可以下官方文档中有比较详细的描述,这种加密一般都是DBA负责的:
加密可以保证数据的安全,但是对数据进行加密也并不是全无缺点的,一般来说存在以下几个缺点: