二、挑战
在真实业务场景中,相关业务开发团队则往往需要针对公司安全部门需求,自行实行并维护一套加解密系统, 如加解密SDK、或加解密服务提供的OpenAPI。然而真正实施过程中会发现有很多让人头疼的问题,如业务代码入侵严重,已上线的业务改造成本大,风险高等等。而彩虹桥针对这些痛点,提供了一套完整的透明化解决方案,实现了业务代码0入侵,安全低风险地无缝进行加密改造。下面我们就来剖析一下整个方案的实现原理。
三、实现原理
3.1 彩虹桥简单介绍
主要针对不熟悉彩虹桥的同学,这里做一下简单介绍。彩虹桥用一句话概括就是基于Apache ShardingSphere二次开发的透明化数据库中间件,通过数据分片、读写分离、影子库、加解密等能力对原有数据库进行增强。目前得物内部主要采用的中心化部署架构和非中心化部署2种方式。
想进一步了解彩虹桥的同学,可以参考我之前写的一篇文章:得物数据库中间件平台“彩虹桥”演进之路
中心化部署架构(Proxy模式)
Proxy模式下,加解密实现模块是在Proxy内部完成,对上层应用完全透明。
- 去中心化部署(JDBC模式)
JDBC模式下,加解密实现模块是在Rainbow内部完成,对上层应用完全透明。
3.2 核心名称解释
在了解原理之前我们先来认识几个基本概念:
名词 | 解释 |
逻辑列 | 用于计算加解密列的逻辑名称,是业务代码中定义的SQL对应的列名称。 |
密文列 | 用于存储加密后的数据,是DB中实际存在的真实列名 |
明文列 | 存储明文的列,用于在加密数据迁移过程中仍旧提供服务,在洗数结束后可以删除。 |
3.3 加解密整体架构
整个过程对上游业务应用完全透明化,主要就是通过彩虹桥的内核模块对SQL进行解析,然后根据加解密规则找出需要加密的字段和所使用的加解密算法对目标字段进行加解密处理后,再将SQL改成于底层DB交互的SQL。彩虹桥会将用户请求的明文进行加密后存储到底层数据库,并在用户查询时将密文从数据库中取出进行解密后返回给上游。通过屏蔽对数据的加密处理,使用户无需感知解析 SQL、数据加密、数据解密的处理过程,就像在使用普通数据一样使用加密数据。
听起来有点抽象,下面举个例子就比较好理解了。
其中phone为逻辑列,phone_cipher为密文列,彩虹桥内部把10086经过加密后,把where条件改成phone_cipher = 'xxx',这里实际查询的是密文列,但是整个上层是无感知的,对业务来说这个字段就是phone,实际查询的数据库列是phone_cipher。
3.4 加密规则
主要是用于告诉彩虹桥哪个逻辑表里哪个列用于存储密文数据(密文列)、使用什么算法加解密、哪个列用于存储明文数据(明文列)以及用户想使用哪个列进行 SQL 编写(逻辑列),在结合上面的例子看,规则配置就应该是这样的。
这里的明文列可能比较难理解,这里单独解释一下,明文列主要用于在加密数据迁移过程中仍旧提供服务,在洗数结束后可以删除。因为已上线业务改造前,数据库里面存储的只有明文,在改造过程前几个阶段查询所用列都是明文列。一般来说明文列可以与逻辑列保持一致。
3.5 整体解决方案详解
3.5.1 新上线业务
新上线业务由于一切从零开始,不存在历史数据清洗问题,所以相对简单。只需要配置好规则,数据层不需要只需要保留一个密文列即可。
3.5.2 已上线业务改造
已上线业务的改造流程相对复杂,由于业务已经在线上运行,数据库里必然存有大量明文历史数据。需要解决的问题是如何让历史数据得以加密清洗、如何让增量数据得以加密处理、如何让业务在新旧两套数据系统之间进行无缝、透明化迁移。
下面我们把整套解决方案拆分成几个阶段来逐个分析。
第一阶段(步骤1~8)- 增量数据双写(明文列、密文列同时维护)、存量数据清洗
步骤2~5主要是新增加密规则,让彩虹桥实现增量的数据的双写(明文列、密文列同时维护),此时查询还是用的明文列。
举个例子:
步骤6~8的存量数据清洗主要是借助数据平台(得物内部数据同步&订阅&迁移中间件)完成,由彩虹桥下发密钥跟对应的库表列信息,数据平台负责把彩虹桥规则生效前的所有历史数据,按照对应加密规则更新密文列。
这里where条件加上 phone = '10086' 是为了保证更新的时候,这条数据的明文从查询出来后没有被其他上游修改过。
第二阶段(步骤9~11)- 查明文列切换成查密文列
当存量数据清洗完成之后,就可以通过开关控制(这里的开关的粒度是列级别)把查明文列切换成查密文列,如果将系统切到密文列进行查询时,发现系统报错,可快速把开关改回去即可恢复,整个过程只对少量查询有损,不会产生脏数据。
举个例子:
第三阶段(步骤12~14)- 停止写明文列,只写密文列
当把读切换到密文列运行一段时间稳定后,就可以通过配置来停止明文列的维护,这时候读写都是走的密文列了。
举个例子:
第四阶段(步骤15)- 数据层明文列清洗
通过DML语句将明文列数据统一刷成无效数据即可,这里不建议DDL删列。
3.5.3 离线解密
大数据或风控团队日常会有一些抽数需求,具体可以分T+1离线抽数、数据实时订阅2种。均可以通过数据平台提供相关解密能力,数据平台内部会调用彩虹桥OpenAPI拿到密钥以及加解密配置,做解密后往下游投递。
3.6 不支持项
加密字段无法支持查询不区分大小写功能;
加密字段无法支持比较操作,如:大于、小于、ORDER BY、BETWEEN、LIKE 等;
加密字段无法支持计算操作,如:AVG、SUM 以及计算表达式。
四、未来规划
密钥动态替换
数据加密是为了防止脱库时一些敏感字段泄露,那如果密钥泄露了,即使做了加密也是徒劳。所以密钥支持动态替换,整个数据安全等级会更上一层楼。具体的实现方式其实也比较简单,就是在密文中嵌入版本号信息,解密的时候根据版本号去匹配对应的密钥即可,同步清洗老版本的密文列即可。
加盐加密
常规的加密算法,同一个明文加密后的密文是一样的,这样很容易被撞库。如果我们在加密的时候加上某个变动种子(加盐加密),这样加密后的密文就非常随机了,很难通过撞库来破解。进一步提升了安全等级。
五、总结
数据安全是一个非常严肃的话题,一旦出现数据泄露,特别是涉及敏感信息,对客户和公司都可能造成不可估量的损失,所以数据加密的必要性不言而喻。对比传统的加解密方案,彩虹桥这种方案优势非常明显,首先是自动化 & 透明化数据加密过程,用户无需关注加密中间实现细节,只需要配置自己需要加密的列,还有彩虹桥内置多种加密算法(MD5/AES/RC4等)可配置,并且可根据实际需要自定义加密算法进行数据加密。特别是大部分场景都是针对已上线业务的改造,在改造过程中彩虹桥可实现明文数据与密文数据同步存储,并通过配置决定使用明文列还是密文列进行查询,可实现在不改变业务查询 SQL 前提下,已上线系统对加密前后数据进行安全、透明化迁移。无论是业务改造成本还是密钥安全性上都具备优势。