【Java】设计一个支持敏感数据存储和传输安全的加解密平台

一、问题解析

在一个应用系统运行过程中,需要记录、传输很多数据,这些数据有的是非常敏感的,比如用户姓名、手机号码、密码、甚至信用卡号等等。这些数据如果直接存储在数据库,记录在日志中,或者在公网上传输的话,一旦发生数据泄露,不但可能会产生重大的经济损失,还可能会使公司陷入重大的公关与法律危机。公司上下辛苦十几年,一夜回到解放前。

所以,敏感信息必须进行加密处理,也就是把敏感数据以密文的形式存储、传输。这样即使被黑客攻击,发生数据泄露,被窃取的数据也是密文,获取数据的人无法得到真实的明文内容,敏感数据依然被保护着。而当应用程序需要访问这些密文的时候,只需要进行数据解密,即可还原得到原始明文数据。加解密处理既保证了数据的安全,又保证了数据的正常访问。

但是,这一切的前提是加密和解密过程的安全。加密、解密过程由加密算法、加密密钥、解密算法、解密密钥组成。下图是一个对称加密、解密过程。对称加密密钥和解密密钥是同一个密钥,调用加密算法可将明文加密为密文,调用解密算法可将密文还原为明文。

所以,如果窃取数据的人知道了解密算法和密钥,即使数据是加密的,也可以轻松对密文进行还原,得到原始的明文数据。而很多时候,解密算法和密钥都以源代码的方式保存在代码仓库里,黑客如果窃取了源代码,或者内部人泄露了源代码,那么所有的秘密就都不是秘密了。

此外,在某些情况下,我们的系统需要和外部系统进行对称加密数据传输,比如和银行加密传输信用卡卡号,这时候涉及到密钥交换,即我方人员和银行人员对接,直接传递密钥。如果因密钥泄露导致重大经济损失,那么持有密钥的人员将无法自证清白,这又会导致没有人愿意保管密钥。

因此,我们设计了一个加解密服务系统,系统名称为“Venus”,统一管理所有的加解密算法和密钥。应用程序只需要依赖加解密服务SDK,调用接口进行加解密即可,而真正的算法和密钥在系统服务端进行管理,保证算法和密钥的安全。

15.1 需求分析

一般说来,日常开发中的加解密程序存在如下问题:

  1. 密钥(包括非对称加解密证书)保存在源文件或者配置文件中,存储分散而不安全。
  2. 密钥没有分片交换机制,不能满足高安全级密钥管理和交换的要求。
  3. 密钥缺乏版本管理,不能灵活升级,一旦修改密钥,此前加密的数据就可能无法解密。
  4. 加密解密算法程序不统一,同样算法不同实现,内部系统之间密文不能正确解析。
  5. 部分加解密算法程序使用了弱加解密算法和弱密钥,存在安全隐患。

为此,我们需要设计开发一个专门的加解密服务及密钥管理系统,以解决以上问题。

Venus是一个加解密服务系统,核心功能是加解密服务,辅助功能是密钥与算法管理。此外,Venus还需要满足以下非功能需求:

  • 安全性需求- 必须保证密钥的安全性,保证没有人能够有机会看到完整的密钥。因此一个密钥至少要拆分成两片,分别存储在两个异构的、物理隔离的存储服务器中 。在需要进行密钥交换的场景中,将密钥至少拆分成两个片段,每个管理密钥的人只能看到一个密钥片段,需要双方所有人分别交接才能完成一次密钥交换。
  • 可靠性需求- 加解密服务必须可靠,即保证高可用。无论在加解密服务系统服务器宕机、还是网络中断等各种情况下,数据正常加解密都需要得到保障。
  • 性能需求- 加解密计算的时间延迟主要花费在加解密算法上,也就是说,加载加解密算法程序、获取加解密密钥的时间必须短到可以忽略不计。

根据以上加解密服务系统功能和非功能需求,系统用例图设计如下:

系统主要参与者(Actor)包括:

系统主要用例过程和功能包括:

  1. 开发工程师使用密钥管理功能为自己开发的应用申请加解密算法和密钥;
  2. 安全工程师使用密钥管理功能审核算法和密钥的强度是否满足数据安全要求;
  3. (经过授权的)密钥管理者使用密钥管理功能可以查看密钥(的一个分片);
  4. 应用程序调用加解密功能完成数据的加密、解密;
  5. 加密解密功能和密钥管理功能调用密钥服务功能完成密钥的存储和读取;
  6. 密钥服务功能访问一个安全、可靠的密钥存储系统读写密钥。

总地说来,Venus应满足如下需求:

  1. 集中、分片密钥存储与管理,多存储备份,保证密钥安全易管理。
  2. 密钥申请者、密钥管理者、密钥访问者,多角色多权限管理,保证密钥管理与传递的安全。
  3. 通过密钥管理控制台完成密钥申请、密钥管理、密钥访问控制等一系列密钥管理操作,实现便捷的密钥管理。
  4. 统一加解密服务API,简单接口,统一算法,为内部系统提供一致的加解密算法实现。

15.2 概要设计

针对上述加解密服务及密钥安全管理的需求,设计加解密服务系统Venus整体结构如下:

应用程序调用Venus提供的加解密SDK服务接口,对信息进行加解密,该SDK接口提供了常用的加密解密算法并可根据需求任意扩展。SDK加解密服务接口调用Venus密钥服务器的密钥服务,以取得加解密密钥,并缓存在本地。而密钥服务器中的密钥则来自多个密钥存储服务器,一个密钥分片后存储在多个存储服务器中,每个服务器都由不同的人负责管理。密钥申请者、密钥管理者、安全审核人员通过密钥管理控制台管理更新密钥,每个人各司其事,没有人能查看完整的密钥信息。

15.2.1 部署模型

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页面,供开发工程师、安全工程师、密钥管理者进行密钥申请、更新、审核、查看等操作。

15.2.2 加解密调用时序图

加解密调用过程如下时序图所示。

  1. 应用程序App调用Venus SDK对数据进行加密(解密)。
  2. SDK检查在本地是否有缓存加解密需要的密钥和加解密算法代码,如果有缓存,就直接使用该算法和密钥进行加解密。
  3. 如果本地没有缓存密钥和算法,请求远程服务器返回密钥和算法。
  4. 部署在Venus服务器的Key Manager收到请求后,访问数据库,检查该应用配置的密钥和算法Meta信息。
  5. 数据库返回的Mata信息中包括了密钥的分片信息和存储位置,Key Manager访问文件服务器和数据库,获取密钥分片,并将多个分片合并成一个完整密钥,返回给客户端SDK。
  6. SDK收到密钥后,缓存在本地进程内存中,并完成对App加解密调用的处理。

通过该设计,我们可以看到,Venus对密钥进行分片存储,不同存储服务器由不同运维人员管理。就算需要进行密钥交换,那么参与交换的人员,每个人也只能获得一个密钥分片,无法得到完整的密钥,这样就保证了密钥的安全性。

密钥缓存在SDK所在的进程(也就是应用程序App所在的进程)中,只有第一次调用时会访问远程的Venus服务器,其他调用只访问本进程缓存。因此加解密的性能只受加解密的数据大小和算法的影响,不受Venus服务的性能影响,满足了性能要求。

同时,由于密钥在缓存中,如果Venus服务器临时宕机,或者网络通信中断,也不会影响到应用程序的正常使用,保证了Venus的可靠性。但是如果Venus服务器长时间宕机,那么应用重新启动,本地缓存被清空,就需要重新请求密钥,这时候应用就不可用了。那么Venus如何在这种情况下仍然保证高可用呢?

解决方案就是对Venus服务器、数据库和文件服务器做高可用备份。Venus服务器部署2-3台服务器,构建一个小型集群,SDK通过软负载均衡访问Venus服务器集群,若发现某台Venus服务器宕机,就进行失效转移。同样,数据库和文件服务器也需要做主从备份。

15.3 详细设计

Venus详细设计主要关注SDK核心类设计。其他的例如数据库结构设计、服务器密钥管理Console设计等,这里不做展开。

15.3.1 密钥领域模型

为了便于SDK缓存、管理密钥信息以及SDK与Venus服务端传输密钥信息,我们设计了一个密钥领域模型,如下图:

  1. 一个应用程序使用的所有密钥信息都记录在KeyBox对象中,KeyBox对象中有一个keySuitMap成员变量,这个map的key是密钥名称,value是一个KeySuit对象。
  2. KeySuit类中有一个keyChainMap成员变量,这个map类的key是版本号,value是一个KeyChain对象。Venus因为安全性需求,需要支持多版本的密钥。也就是说,对同一类数据的加密密钥过一段时间就会进行版本升级,这样即使密钥泄露,也只会影响一段时间的数据,不会导致所有的数据都被解密。
  3. KeySuit类的另一个成员变量currentVersion记录当前最新的密钥版本号,也就是当前用来进行数据加密的密钥版本号。而解密的时候,则需要从密文数据中提取出加密密钥版本号(或者由应用程序自己记录密钥版本号,在解密的时候提供给Venus SDK API),根据这个版本号获取对应的解密密钥。
  4. 具体每个版本的密钥信息记录在KeyChain中,包含了密钥名称name、密钥版本号version、加入本地缓存的时间cache_time、该版本密钥创建的时间versionTime、对应的加解密算法algorithm,当然,还有最重要的密钥分片列表keyChipList,里面按序记录着这个密钥的分片信息。
  5. KeyChip记录每个密钥分片,包括分片编号no,以及分片密钥内容chip。

15.3.2 核心服务类设计

应用程序通过调用加解密API VenusService完成数据加解密。如下图:

  1. Venus SDK的核心类是VenusService,应用程序调用该对象的encrypt方法进行加密,decrypt方法进行解密。应用程序需要构造VenusData对象,将加解密数据传给VenusService,VenusService加解密完成后创建一个新的VenusData对象,将加解密的结果写入该对象并返回。VenusData成员变量在后面详细讲解。
  2. VenusService通过VenusConnector类连接Venus服务器获取密钥KeyBox和算法Algorithm,并调用Algorithm的对应方法完成加解密。

以加密为例,具体处理过程时序图如下:

首先,应用程序App创建VenusData对象,并将待加密数据写入该对象。接着,App调用VenusService的encrypt方法进行加密,VenusService检查加密需要的密钥和算法是否已经有缓存,如果没有,就调用VenusConnector请求服务器,返回密钥和算法。VenusConnector将根据返回的算法字节码来构造加密算法的实例对象,同时根据返回的密钥构造相关密钥对象,并写入KeyBox,完成更新。

下一步,VenusService会根据更新后的KeyBox中的密钥和算法进行加密,并将加密结果写入VenusData。最后,应用程序App从返回的VenusData中获取加密后的数据即可。

15.3.3 加解密数据接口VenusData设计

VenusData用于表示Venus加解密操作输入和输出的数据,也就是说,加解密的时候构造VenusData对象调用Service对应的方法,加解密完成后返回值还是一个VenusData对象。

VenusData包含的属性如下图:

VenusData用作输入时:

  1. 属性bytes和text只要设置一个,即要么处理的是二进制bytes数据,要么是Striing数据,如果两个都设置了,Venus会抛出异常。
  2. 属性version可以不设置(即null),表示Venus操作使用的密钥版本是当前版本。
  3. 属性outputWithText表示输出的VenusData是否处理为text类型,缺省值是true。
  4. 属性dataWithVersion表示加密后的VenusData的bytes和text 中是否包含使用密钥的版本信息,这样在解密的时候可以不指定版本,缺省值是false。

如果dataWithVersion设置为true,即表示加密后密文内包含版本号,这种情况下,VenusService需要在密文头部增加3个字节的版本号信息,其中头两个字节为固定的magic code:0x5E、0x23,第三个字节为版本号(也就是说,密钥版本号只占用一个字节,最多支持256个版本)。

VenusData用作输出时,Venus会设置属性keyName(和输入时的值一样)、version、 bytes、 outputWithText、dataWithVersion(和输入时的值一样),并根据输入的 outputWithText决定是否设置text属性。

15.3.4 测试用例代码demo

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 ”即可获取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/675473.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

极海APM32F072用Keil5烧录失败Error: Flash Download failed -“Cortex-MO+“

在用Keil5烧录时,出现错误弹窗,大概长这样: 检查了一圈设置,都搞不好。 先用J-Flash,显示读写保护(未截图),会跳出界面让选择是否解除读写保护: 1.点击允许读操作YES&am…

循环购模式!增加用户复购的不二之选!

大家好,我是吴军,来自一家专注于软件开发与商业模式设计的公司。我们主要业务是构建商城系统,并为各类企业提供全面的商业模式解决方案。目前,我们已经成功开发了超过200种独特的商业模式,帮助许多企业实现了他们的商业…

C++_deque:deque的数据结构特点

文章目录 🚀1. deque介绍🚀2. deque数据结构🚀3. deque的缺陷🚀4.为什么选择deque作为stack和queue的底层默认容器🚀5.deque头插逻辑(了解) 大家好!本文会简单讲讲deque的使用与数据…

实现流程化办公,可以相信拖拽表单设计器!

当前,竞争压力越来越大,利用什么样优良的办公软件实现流程化办公?可以一起来了解低代码技术平台、拖拽表单设计器的优势特点,看看它们是如何助力企业降本、增效、提质的。低代码技术平台的优势特点多,可以助力企业用拖…

第99天:权限提升-数据库提权口令获取MYSQLMSSQLOracleMSF

案例一:提权条件-数据库帐号密码获取方式 提权条件 - 数据库帐号密码获取方式 0 、网站存在高权限 SQL 注入点 1 、数据库的存储文件或备份文件 2 、网站应用源码中的数据库配置文件 3 、采用工具或脚本爆破 ( 需解决外联问题 ) sql注入点 xhcms后台管理系统…

刷新页面控制台莫名奇妙报错显示/files/test_files/file_txt.txt

今天突然发现每次刷新页面都有几个报错,不刷新页面就没有。 这个报错应该不是我们系统的问题,是因为装了浏览器插件的原因。比如我安装了 大家有没有遇到类似的问题。

MyBatis快速入门教程

文章目录 一、介绍什么是持久层为什么要学MyBatis? 二、如何获得MyBatis?三、第一个Mybatis程序数据库导入maven依赖bean 实体类dao持久层resources编写对应的映射文件 mybatis主配置文件测试类运行遇到报错Could not find resource com/qibu/dao/IUserD…

Park Here:城市停车新神器,让停车不再难

在现代城市的快节奏生活中,停车问题往往成为驾驶者的一大困扰。无论是寻找停车位时的焦虑,还是对停车规则的不了解,都让停车变得不那么简单。然而,随着科技的发展,一款名为“Park Here”的移动应用程序正逐渐改变这一现…

论文精读--Swin Transformer

想让ViT像CNN一样分成几个block,做层级式的特征提取,从而使提取出的特征有多尺度的概念 Abstract This paper presents a new vision Transformer, called Swin Transformer, that capably serves as a general-purpose backbone for computer vision. …

做了几年的广告设计,发现一些东西

我换了多个行业,发现了一些广告设计的一些行业规律,先从面试说起。 他们面试比较倾向是本行业的,找到他们去当前公司来当设计,但是重点;还是不喜欢我这种经常被试用期不合格的情况。 还有甲方公司,经常需要…

【机器学习】【遗传算法】【项目实战】药品分拣的优化策略【附Python源码】

仅供学习、参考使用 一、遗传算法简介 遗传算法(Genetic Algorithm, GA)是机器学习领域中常见的一类算法,其基本思想可以用下述流程图简要表示: (图参考论文:Optimization of Worker Scheduling at Logi…

EMQX Enterprise 5.7 发布:新增会话持久化、消息 Schema 验证、规则引擎调试与追踪功能

EMQX Enterprise 5.7.0 版本现已正式发布! 在这个版本中,我们引入了一系列新的功能和改进,包括会话持久化、消息 Schema 验证、规则引擎调试与追踪测试等功能。此外,新版本还进行了多项改进以及 BUG 修复,进一步提升了…

QT 编译Lua 动态库,使用Lua脚本混合编程

一,编译Lua动态库 1,下载lua源码 地址:Lua: downloadhttps://www.lua.org/download.html 2,配置 解压lua源码压缩包,里面有个src文件夹,里面的代码就是lua的源码

TMS320F280049 ECAP模块--capture模式(1)

功能框图 event预分频 如下图所示,可以对输入信号进行预分频。 一次性触发和连续触发 如下图所示,可以进行一次性触发,也可以进行连续触发。 中间计数器的clk是事件1-4,stop是由一次性触发逻辑控制,rst是由ctrfiltre…

【数据结构与算法 经典例题】(C语言)反转链表图文详解

💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《数据结构与算法 经典例题》C语言 期待您的关注 ​ 目录 一、问题描述 二、解题思路分析 三、代码实现 一、问题描述 二、解题…

华为机考入门python3--(33)牛客33-整数与IP地址间的转换

分类:进制转换 知识点: 十进制转8位二进制 format(num, 08b) 二进制转十进制 int(binary_str, 2) 列表中元素类型转换 new_list map(int, old_list) 题目来自【牛客】 # 将IP地址转换为十进制形式的整数 def ip_to_int(ip):# map返回的是迭…

SEO之关键词扩展(一)

初创企业搭建网站的朋友看1号文章;想学习云计算,怎么入门看2号文章谢谢支持: 1、我给不会敲代码又想搭建网站的人建议2、新手上云 确定了核心关键词后,接下来就是进行关键词扩展。对一个稍有规模的网站来说,研究几十个…

【计算机毕设】【计算机毕设】基于SpringBoot平台的医疗病历交互系统设计与实现 - 源码免费(私信领取) - 源码免费(私信领取)

免费领取源码 | 项目完整可运行 | v:chengn7890 诚招源码校园代理! 1. 研究目的 本项目旨在设计并实现一个基于SpringBoot的医疗病历交互系统,以改善病历管理和医患沟通的效率,提升医疗服务质量。具体目标包…

质数计数问题求解

质数计数问题求解 题目 leetcdoe204 计数质数:https://leetcode.cn/problems/count-primes 给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。 示例1: 输入:n = 10 输出:4 解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 示例 2: 输入:n = 0 输出:0 示…

Go 线程同步

一、介绍 通常在 Go 语言中有两种方法可以用来做线程同步 sync.Cond channel channel 的很好理解,当我们从一个 channel 中接收数据的时候,如果里面没有数据,那我们直接就阻塞在那里了。 在 Go 语言中,如果你尝试在已经持有某…