赞
踩
在一个应用系统运行过程中,需要记录、传输很多数据,这些数据有的是非常敏感的,比如用户姓名、手机号码、密码、甚至信用卡号等等。这些数据如果直接存储在数据库,记录在日志中,或者在公网上传输的话,一旦发生数据泄露,不但可能会产生重大的经济损失,还可能会使公司陷入重大的公关与法律危机。公司上下辛苦十几年,一夜回到解放前。
所以,敏感信息必须进行加密处理,也就是把敏感数据以密文的形式存储、传输。这样即使被黑客攻击,发生数据泄露,被窃取的数据也是密文,获取数据的人无法得到真实的明文内容,敏感数据依然被保护着。而当应用程序需要访问这些密文的时候,只需要进行数据解密,即可还原得到原始明文数据。加解密处理既保证了数据的安全,又保证了数据的正常访问。
但是,这一切的前提是加密和解密过程的安全。加密、解密过程由加密算法、加密密钥、解密算法、解密密钥组成。下图是一个对称加密、解密过程。对称加密密钥和解密密钥是同一个密钥,调用加密算法可将明文加密为密文,调用解密算法可将密文还原为明文。
所以,如果窃取数据的人知道了解密算法和密钥,即使数据是加密的,也可以轻松对密文进行还原,得到原始的明文数据。而很多时候,解密算法和密钥都以源代码的方式保存在代码仓库里,黑客如果窃取了源代码,或者内部人泄露了源代码,那么所有的秘密就都不是秘密了。
此外,在某些情况下,我们的系统需要和外部系统进行对称加密数据传输,比如和银行加密传输信用卡卡号,这时候涉及到密钥交换,即我方人员和银行人员对接,直接传递密钥。如果因密钥泄露导致重大经济损失,那么持有密钥的人员将无法自证清白,这又会导致没有人愿意保管密钥。
因此,我们设计了一个加解密服务系统,系统名称为“Venus”,统一管理所有的加解密算法和密钥。应用程序只需要依赖加解密服务SDK,调用接口进行加解密即可,而真正的算法和密钥在系统服务端进行管理,保证算法和密钥的安全。
一般说来,日常开发中的加解密程序存在如下问题:
为此,我们需要设计开发一个专门的加解密服务及密钥管理系统,以解决以上问题。
Venus是一个加解密服务系统,核心功能是加解密服务,辅助功能是密钥与算法管理。此外,Venus还需要满足以下非功能需求:
根据以上加解密服务系统功能和非功能需求,系统用例图设计如下:
系统主要参与者(Actor)包括:
系统主要用例过程和功能包括:
总地说来,Venus应满足如下需求:
针对上述加解密服务及密钥安全管理的需求,设计加解密服务系统Venus整体结构如下:
应用程序调用Venus提供的加解密SDK服务接口,对信息进行加解密,该SDK接口提供了常用的加密解密算法并可根据需求任意扩展。SDK加解密服务接口调用Venus密钥服务器的密钥服务,以取得加解密密钥,并缓存在本地。而密钥服务器中的密钥则来自多个密钥存储服务器,一个密钥分片后存储在多个存储服务器中,每个服务器都由不同的人负责管理。密钥申请者、密钥管理者、安全审核人员通过密钥管理控制台管理更新密钥,每个人各司其事,没有人能查看完整的密钥信息。
Venus部署模型如图:
Venus系统的核心服务器是Key Server服务器,提供密钥管理服务。密钥分片存储在文件服务器File Store和数据库DB中。
使用Venus加解密服务的应用程序(Application)部署在应用程序服务器(App Server)中,依赖Venus提供的SDK API进行数据加解密。而Venus SDK 则是访问密钥服务器(Key Server)来获取加解密算法代码和密钥。
安全起见,密钥将被分片存储在文件服务器(Key File Store)和数据库服务器(Key DB)中。所以Key Server服务器中部署了密钥管理组件(Key Manager),用于访问数据库中的应用程序密钥元信息(Key Meta Data),以此获取密钥分片存储信息。Key Server服务器根据这些信息访问File Store和DB,获取密钥分片,并把分片拼接为完整密钥,最终返回给SDK。
此外,密钥管理控制台(Key Console)提供一个web页面,供开发工程师、安全工程师、密钥管理者进行密钥申请、更新、审核、查看等操作。
加解密调用过程如下时序图所示。
通过该设计,我们可以看到,Venus对密钥进行分片存储,不同存储服务器由不同运维人员管理。就算需要进行密钥交换,那么参与交换的人员,每个人也只能获得一个密钥分片,无法得到完整的密钥,这样就保证了密钥的安全性。
密钥缓存在SDK所在的进程(也就是应用程序App所在的进程)中,只有第一次调用时会访问远程的Venus服务器,其他调用只访问本进程缓存。因此加解密的性能只受加解密的数据大小和算法的影响,不受Venus服务的性能影响,满足了性能要求。
同时,由于密钥在缓存中,如果Venus服务器临时宕机,或者网络通信中断,也不会影响到应用程序的正常使用,保证了Venus的可靠性。但是如果Venus服务器长时间宕机,那么应用重新启动,本地缓存被清空,就需要重新请求密钥,这时候应用就不可用了。那么Venus如何在这种情况下仍然保证高可用呢?
解决方案就是对Venus服务器、数据库和文件服务器做高可用备份。Venus服务器部署2-3台服务器,构建一个小型集群,SDK通过软负载均衡访问Venus服务器集群,若发现某台Venus服务器宕机,就进行失效转移。同样,数据库和文件服务器也需要做主从备份。
Venus详细设计主要关注SDK核心类设计。其他的例如数据库结构设计、服务器密钥管理Console设计等,这里不做展开。
为了便于SDK缓存、管理密钥信息以及SDK与Venus服务端传输密钥信息,我们设计了一个密钥领域模型,如下图:
应用程序通过调用加解密API VenusService完成数据加解密。如下图:
以加密为例,具体处理过程时序图如下:
首先,应用程序App创建VenusData对象,并将待加密数据写入该对象。接着,App调用VenusService的encrypt方法进行加密,VenusService检查加密需要的密钥和算法是否已经有缓存,如果没有,就调用VenusConnector请求服务器,返回密钥和算法。VenusConnector将根据返回的算法字节码来构造加密算法的实例对象,同时根据返回的密钥构造相关密钥对象,并写入KeyBox,完成更新。
下一步,VenusService会根据更新后的KeyBox中的密钥和算法进行加密,并将加密结果写入VenusData。最后,应用程序App从返回的VenusData中获取加密后的数据即可。
VenusData用于表示Venus加解密操作输入和输出的数据,也就是说,加解密的时候构造VenusData对象调用Service对应的方法,加解密完成后返回值还是一个VenusData对象。
VenusData包含的属性如下图:
VenusData用作输入时:
如果dataWithVersion设置为true,即表示加密后密文内包含版本号,这种情况下,VenusService需要在密文头部增加3个字节的版本号信息,其中头两个字节为固定的magic code:0x5E、0x23,第三个字节为版本号(也就是说,密钥版本号只占用一个字节,最多支持256个版本)。
VenusData用作输出时,Venus会设置属性keyName(和输入时的值一样)、version、 bytes、 outputWithText、dataWithVersion(和输入时的值一样),并根据输入的 outputWithText决定是否设置text属性。
- publicstaticvoidtestVenusService()throws Exception {
- // 准备数据VenusDatadata1=newVenusData();
- data1.setKeyName("aeskey1");
- data1.setText("PlainText");
- // 加密操作VenusDataencrypt= VenusService.encrypt(data1);
- System.out.printf("Key Name: %s, Secret Text: %s, Version: %d.\n", encrypt.getKeyName(),
- encrypt.getText(), encrypt.getVersion());
- // 准备数据VenusDatadata2=newVenusData();
- data2.setKeyName("aeskey1");
- data2.setBytes(encrypt.getBytes());
- data2.setVersion(encrypt.getVersion());
- // 解密操作VenusDatadecrypt= VenusService.decrypt(data2);
- System.out.printf("Key Name: %s, Plain Text: %s, Version: %d.\n", decrypt.getKeyName(),
- decrypt.getText(), decrypt.getVersion());
- }
最近很多同学问我有没有java学习资料,我根据我从小白到架构师多年的学习经验整理出来了一份80W字面试解析文档、简历模板、学习路线图、java必看学习书籍 、 需要的小伙伴 可以关注我
公众号:“ 灰灰聊架构 ”, 回复暗号:“ 159 ”即可获取
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。