✅数据库怎么做加密和解密?

典型回答

很多时候,我们的数据库表中会存储很多敏感信息,如用户的手机号、身份证号、密码之类的,这些数据如果不做好加密的话,一旦数据泄漏就会导致重要信息泄露。

一般来说都需要对敏感字段进行加密,然后再在数据库中保存加密后的数据,这样即使被拖库也没关系,比如攻击者拿到的只是加密后的密码,并不知道真实密码是什么。

✅什么是撞库、拖库和洗库?

那么,我们应该如何做数据库的加密呢。通常来说有以下几种办法:

服务端加解密

服务端加解密指的就是数据库在存入数据库之前就加密好,然后再从数据库取出之后进行解密。这样可以保证数据库的数据绝对安全,因为数据库也不知道明文到底是什么。

一般来说我们可以选择各种各样的加密算法,如对称加密和非对称加密都可以,一般来说用对称加密就行了。

✅什么是对称加密和非对称加密?

当然,有些场景下也可以用MD5(MD5严格来说并不是加密算法,只是一种hash算法),但是需要注意的是MD5不支持解密,所以只能用于那种存储后只做匹配而不作查询展示的场景,如用户的密码。而需要展示的场景,如手机号等就需要支持解密。

数据库加密函数

MySQL提供了一些内置的加密函数,我们可以直接使用这些加密函数进行数据加密:

  1. AESENCRYPT 和 AESDECRYPT,这两个函数是对称加密算法,使用对称密钥加密,这意味着加密和解密都使用相同的密钥。因此,必须确保密钥的安全性。
    • AESENCRYPT(str, key) 用于使用AES算法对字符串 str 进行加密,key表示使用的密钥。
    • AESDECRYPT(cryptstr, key) 用于解密已加密的字符串 cryptstr,使用相同的密钥 key。
-- 加密数据
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';
  1. ENCRYPT: ENCRYPT(str, salt) 函数使用UNIX crypt()函数对字符串 str 进行加密,其中 salt 是一个2字符的随机盐。这种加密方法通常用于密码存储,但不是最安全的加密方式。
-- 使用随机盐加密密码
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);
  1. MD5 和 SHA1:
    • MD5(str) 和 SHA1(str) 函数分别用于计算字符串 str 的MD5和SHA-1哈希值。这不是真正的加密,而是散列函数,无法逆向解密。
-- 存储MD5哈希值
INSERT INTO user_data (username, password_hash) VALUES ('Hollis', MD5('hollis666'));

-- 验证密码
SELECT * FROM user_data WHERE username = 'Hollis' AND password_hash = MD5('hollis666');
  1. PASSWORD: PASSWORD(str) 函数将字符串 str 加密为MySQL原生密码散列。这通常用于MySQL用户密码的存储。
-- 存储MySQL原生密码散列
INSERT INTO mysql_users (username, password_hash) VALUES ('Hollis', PASSWORD('hollis666'));
  1. DESENCRYPT 和 DESDECRYPT,需要注意:DES算法不够安全,通常不建议使用:
    • DESENCRYPT(str, keystr) 用于使用DES算法对字符串 str 进行加密,使用提供的密钥字符串 keystr。
    • DESDECRYPT(cryptstr, keystr) 用于解密已加密的字符串 cryptstr,使用相同的密钥字符串 keystr。

InnoDB静态加密

MySQL 5.7开始,InnoDB支持对静态数据加密。适用于按表的文件表空间、常规表空间、mysql系统表空间、redolog和undolog进行加密。

从MySQL 8.0.16开始,还支持为schema和常规表空间设置默认加密,这允许DBA控制是否对在这些schema和表空间中创建的表进行加密。

关于表空间的加密,大家可以下官方文档中有比较详细的描述,这种加密一般都是DBA负责的:

https://dev.mysql.com/doc/refman/8.0/en/innodb-data-encryption.html#innodb-schema-tablespace-encryption-default

扩展知识

加密后会带来哪些问题

加密可以保证数据的安全,但是对数据进行加密也并不是全无缺点的,一般来说存在以下几个缺点:

  • 性能开销:加密和解密数据会引入额外的计算开销,这可能导致数据库性能下降。加密操作通常需要更多的CPU资源,因此在高负载环境中,可能需要更强大的硬件来维持性能水平。
  • 复杂性:加密引入了复杂性,包括密钥管理、加密算法的选择和配置等。不正确的配置和管理可能导致数据泄露或安全漏洞。
  • 查询和检索困难:加密数据的查询和检索通常更加困难,尤其是在进行模糊查询或部分匹配时。需要采用额外的技术来解决这些问题。
  • 密钥管理:密钥管理是关键的问题。如果加密密钥不受良好的保护,那么整个安全性可能会受到威胁。密钥管理要求严格的访问控制和监控,以防止未经授权的访问。如果你丢失了加密密钥,那么加密数据将无法解密,这可能导致数据永久不可用。

原文: https://www.yuque.com/hollis666/xkm7k3/xg32pfnstsrh9pdp