数字加密系统设计
1.背景
用MYSQL存放员工的工资信息,因为此信息比较敏感,一旦被泄密会导致很严重的后果,而且不加密的数据容易被篡改,并且不容易发现问题,所以我们需要对员工的工资等信息进行加密。
加密的好处:
能够对敏感信息进行保护,开发人员都无法接触到用户的敏感信息,并且数据一旦被篡改,会导致解密失败,开发人员能及时发现问题风险并解决
2.加密方案
第一种:异或方案
原理:对一个整数进行异或另一个相同的数两次,可以还原这个数字,例如:
System.out.println(122333^23333^23333);
System.out.println(3445566^245444^245444);
输出:
122333
3445566
0 ^1^1 = 0
1^0^0=1
0^0^0=0
1^1^1=1
以此类推得到 a^b^b=a
实际中的应用:如果我们要对一张图片进行加密,可以和对方商量好一个数字秘钥,将图片进行二进制编码后,对每个数字和数字秘钥进行异或得到另一个二进制序列,将这个序列传输给对方,对方拿到这个二进制序列,对每个数字进行异或处理后还原图片。
mysql对数字字段进行加密处理sql:
select (TRUNCATE(number0,0)^175533417+(number0-TRUNCATE(number0,0))) AS field_0 from table_0
解密和加密sql一样,都是先分离出整数和小数部分,对整数部分进行异或加密后与小数部分相加
缺点:对数字秘钥的大小选定较难,太大太小都起不到较好的作用,并且对数据进行篡改后也无法进行告警,数字秘钥必须为正数,因为正数和任意数做异或后,正负数由任意数的正负决定,否则在截取小数部分时会有问题,而且对大于-1的负数例如-0.2222这中小数需要特殊处理,因为0的补码正数和负数是一样的,所以最终的处理sql变成:
CASE
WHEN number0 >= 0 THEN
CAST(
CAST(
TRUNCATE ( number0, 0 ) ^ ( **** ) AS DECIMAL ( 50, 20 )
) + CAST(
( number0 - TRUNCATE ( number0, 0 ) ) AS DECIMAL ( 50, 20 )
) AS DECIMAL ( 50, 20 )
) ELSE - CAST(
CAST(
TRUNCATE ( - number0, 0 ) ^ ( **** ) AS DECIMAL ( 50, 20 )
) + CAST(
(
- number0 - TRUNCATE ( - number0, 0 )
) AS DECIMAL ( 50, 20 )
) AS DECIMAL ( 50, 20 )
)
END
注:****为数字秘钥,字段较多的话sql较长,可以将此语句自定义成mysql的函数。
第二种:AES对称加密
AES加密算法大家都比较熟悉,网上有很多文章可以参考
mysql支持aes算法,加密sql为:
SELECT to_base64(aes_encrypt(number0, 'UBwNsCM7oOA2LkOhXYONIg')) as field_0 from table_0
UBwNsCM7oOA2LkOhXYONIg为AES加密和解密的秘钥
解密sql:
SELECT aes_decrypt(from_base64(string0), 'UBwNsCM7oOA2LkOhXYONIg')) AS field_0 from table_0
3.效率比较
AES加密异或加密
字段个数是指数据库中进行加密的字段数量,测试条数是指相关的数据库记录数。
结果对比:AES加密和异或加密性能相差不大,但是异或加密私密性肯定没AES加密好,而且AES加密后的数据一旦进行篡改就无法进行解密,异或加密做不到这一点。所以本文建议对数字加密采用AES方案较好
4.秘钥的生成问题
假设我们有多个企业员工的工资数据需要保存,如果我们只保存一个全局的秘钥,如果该秘钥被泄漏,会导致数据库中所有企业的数据会存在风险,所以本文建议的方案是可以按照企业的维度进行秘钥生成,并且对接阿里云KMS进行秘钥的生成,每个企业生成一个唯一的秘钥。具体秘钥生成方案如下:
加密过程:
1.通过KMS控制台,或者调用CreateKey接口,创建一个用户主密钥。
- 调用KMS服务的GenerateDataKey接口创建一个数据密钥。KMS会返回一个明文的数据密钥和一个密文的数据密钥。
- 使用明文的数据密钥加密文件,产生密文文件,然后销毁内存中的明文密钥。
-
用户将密文数据密钥和密文文件一同存储到持久化存储设备或服务中。
加密流程
解密过程:
- 从本地文件中读取密文数据密钥。
- 调用KMS服务的Decrypt接口,将加密过的密钥解密为明文密钥。
- 用明文密钥为本地数据解密,再销毁内存中的明文密钥。
总结:设计一个本地秘钥表如图所示,该表存放加密后的每个企业的秘钥,当需要获取数据的时候,从该表获取该企业加密后的秘钥,拿这个加密后的秘钥去kms获取解密后的明文秘钥,用这个秘钥做数据解密操作。
本地秘钥表
注:采用AES加密,数字字段在数据库中的存储类型必须为字符类型