一、想法
- 对于密码的安全不容忽视,密码由终端用户产生,并经过网络,被服务器处理,最后存储于存储设备中。
- 密码必须加密存储,即使数据库泄露也不会导致系统被击破。
- 同时还要考虑到服务器也会存在源码泄露的可能,因此应该考虑到即使源码和数据均被暴露,攻击者也无法加以利用。
二、设计
核心:
- 抛开具体的实现,密码传输和加密过程如果足够安全,则很大程度上可以防范密码的破解。
- 1、对于前端提交的密码,除了期望基于https的加密传输过程,还应对传输过程的敏感数据进行进一步的加密处理。在客户端产生密码明文后,可以通过两步来加强密码的安全传输保障,
第一步,因为服务器保存明文密码是非常不规范的,密码的保存仅需要满足能够支持验证即可,因此,初始明文密码可以直接使用单向唯一不可逆的哈希加密方法,产生密码哈希密文。
第二步,因为无法保证网络传输的安全性,可以再把密码哈希密文进行双向加密后传输,到达服务器后进行解密操作。 - 2、服务器端拿到密码解密后,不管得到的是明文还是密文,都应进行足够安全的加密过程。只需要保证加密工序之后的密文能够对原始密码进行验证这一点即可。
- 3、基于现代计算机运算能力的大环境,以及各项技术和规则未能完全保证数据安全的前提,服务器端的密码加密首先考虑是数据暴露后的破解难度、逆向工厂的资源时间代价。像单向哈希的MD5加密算法和对称可解密的DES算法,因为当前的计算能力已经能够造成危险。
- 4、加密工具不要自己创造,使用公认安全的。
三、加密方法选择
- 1、客户端使用足够强度的sha512进行单向加密,考虑到sha512加密生成速度较快不用影响体验。
- 2、sha512密文使用RSA算法对称加密,再经过网络传输给服务器。rsa属于非对称加密,由于私钥只保存在服务器端,因此破解难度较大,也是目前公认比较安全的。
- 3、服务器RSA解密后,第一步再次进行SHA512加密
- 4、服务器对SHA512密文进行BCriypt类型的加密。BCrypt的特点是,正向加密和验证所需时间和计算资源较少,而反向的破解则计算非常缓慢,也是故意为此设计的。
- 5、得到bcrypt密文后,可选的,再次进行一次对称加密,使用AES对称加密算法,强度足够,需要保管好密钥,而且使用动态密钥更加安全。
4、加密的简单实现
4.1 技术选择
- 为了让以上想法得到快速的实现和验证,
- web直接选择能立刻部署的spring boot,
- 数据库使用常用的mysql,
- 整合随便一个jpa层访问数据,
- 客户端浏览器前端页面,满足有两个输入框和提交按钮即可,这里选用开箱即用的layui样式和thymeleaf模板做简单的数据渲染。
- 浏览器客户端的所有加密只需要引入对应js文件,找到安全的sha512和rsa加密js文件,
- 关键点是SHA512、BCriypt和AES的后端实现,jdk自带的SHA512还需封装相关参数才能达到安全要求否则使用默认配置。由于暂时不涉及安全模块配置,所以可以单独引用bcrypt的相关jar包
4.2编码实现
- 1、直接start.spring.io生成项目,并添加shiro-core依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--...-->
<dependencies>
<!--视图模板-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--web访问-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--加密解密工具-->
<dependency>
<groupId>jbcrypt</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.3</version>
</dependency>
<!--<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.3</version>
</dependency>-->
<!--访问数据库-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--测试-->
<dependency>