加密是开发中或多或少都会遇到的问题,本文阐述了常见的加密类型和加密方式,并以https的ssl过程为例分析各种加密以及认证方式。
若有描述不清楚或者错误的地方还请大家留言斧正
1加密方式
1> 加密类型
对称加密
加密和解密使用的是同一个秘钥,又称私钥加密,特点:速度快,适合大量数据,缺点:秘钥管理和分配存在风险 ,若采用一组秘钥则存在泄漏问题,若由服务端维护多组秘钥则存在秘钥发往客户端被劫持问题
非对称加密
分为公钥和私钥,又称为公钥加密,公钥加密私钥解密(数据加密),当然也可以私钥加密公钥解密(数据签名) ,优点:安全性高,缺点:速度慢于对称加密, 虽然正反都能用,但若采用私钥加密公钥解密,则任何公钥都可以解密 即,存在单方面安全
- 公钥加密私钥解密,即获想要获取数据的一方是秘钥颁布放,这属于别人用我的公钥加密数据传输给我,我使用私钥解密,即使数据丢失别人没有私钥也无法解读
- 私钥加密公钥解密,解密一方是公钥方,即我把公钥给谁谁就可以解密看到,常用来做签名保证数据是有私钥持有者发出且可用的
你只要想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
案例:jwt的RSA采用私钥加密(认证服务),公钥解密(网关服务)的方式
散列算法(签名认证)
又称哈希函数,是一种单项加密算法,他对不同长度的输入消息产生固定长度的输出。散列算法是不可逆的,严格上说不属于加密而是签名
2> 常见的加密手段
1、对称加密
DES、3DES、AES、HS256 (JWT的对称加密)
2、非对称加密
RSA(RS256 ,jwt的对称加密就是采用RSA这种方式)、DSA、ECC
3、散列算法
用途:主要用于验证,防止信息被修。具体用途如:文件校验、数字签名、鉴权协议
SHA1、HMAC、MD5 是常见的散列算法
MD5是一种不可逆的加密算法,目前是最牢靠的加密算法之一,尚没有能够逆运算的程序被开发出来,它对应任何字符串都可以加密成一段唯一的固定长度的代码。
md5散列算法会将不同长度的输入,加密为指定长度的输出, 般有两种16位和32位(16位取的是32的9-24)字符串区分大小写
md5加密理论上依旧可以被大型的彩虹表破解(固定数值加密后内容一致),我们可以通过加盐来降低被破解的风险, 所谓的盐值、其实就是固定或随机的字符串拼接在密码之后
1234采用md5加密后的结果为: 81dc9bdb52d04dc20036dbd8313ed055
当盐值为1,即1234+1拼接其结果为
f190ce9ac8445d249747cab7be43f7d5,
可以看出相邻字符串加密得到的结果是不具备一致性的如12345加密与1234无任何关系
827ccb0eea8a706c4c34a16891f84e7b
- Java中进行md5加密
/*java中的加密方式*/
1>
try {
// 生成一个MD5加密计算摘要
MessageDigest md = MessageDigest.getInstance("MD5");
// 计算md5函数
md.update(str.getBytes());
// digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
// BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
//一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方)
return new BigInteger(1, md.digest()).toString(16);
} catch (Exception e) {
e.printStackTrace();
return null;
}
2>
MessageDigest md5 = null;
md5 = MessageDigest.getInstance("MD5");
byte[] bytes = md5.digest((password + salt).getBytes());
String result = "";
for (byte b : bytes) {
String temp = Integer.toHexString(b & 0xff);
if (temp.length() == 1) {
temp = "0" + temp;
}
result += temp;
}
return result;
3> spring提供的方式
DigestUtils.md5DigestAsHex(password.getBytes());
- vue中
1> 首先安装md5 js
npm install --save js-md5
2> 引入并使用
import md5 from 'js-md5'
md5('holle')
常用场景:
- 前端输入密码加密,我们通常会进行两次加密,第一次在前端通过md5+固定盐值的方式加密 ,这是为了确保在请求传输过程中不会被轻易得到密码,在服务端会采用md5+随机盐值
4、base64算法
理论上不属于加密,是一种可逆的算法,用于二进制->字符的转换,便于请求传输
2 https的加密过程-通过这一过程了解加密、证书
经典的加密博客,道格、苏珊、鲍布,http://www.youdzone.com/signature.html
中文 https://www.jianshu.com/p/c77175dc49f5?from=timeline@
1> Http和Https
Https = Http + SSL/TSL
这里不详细解释SSL、大家知道他是一种数据安全协议即可
SSL和TLS的主要区别?
TLS的主要目标是使SSL更安全,并使协议的规范更精确和完善。另外,TLS版本号也与SSL的不同(TLS的版本1.0使用的版本号为SSLv3.1)
这里解答一个疑问,有人说https是加密的为啥我在浏览器进行F12看到是依旧是明文呢,大家要注意https是通讯过程的加密,数据到达浏览器已经是应用层了,此时数据已经完成解密了。
2> Https加密的演变过程(ssl的实现)
1、对称加密
客户端和服务端使用同一把钥匙、加密过程就像上锁,有钥匙就能打开,所有的人都是用同一把钥匙,一旦钥匙泄露通讯则不安全,若是给每个人都配一把不同的钥匙、则需要由服务端去分发钥匙,但是分发钥匙的过程是不安全的。
问题: key唯一不安全容易泄露、不唯一存在分发过程的安全性
2、非对称加密
服务端维护两把钥匙可以配合使用加密解密,客户端通公钥加密,服务端通过私钥解密,即使被拦截也无法得知请求内容。但是服务端无法回传给客户端信息,如果使用私钥加密则任何公钥都可以解密
问题:双通单通道安全
3、对称+非对称
首先客户端请求服务器公钥,在客户单生成一个 对称加密的字符串 ,然后用公钥加密传输,此时只有服务端的私钥可以解密。二者之后的通讯均采用定制好的对称加密秘钥。
如图:黑客在第一次请求的时候就拦截到了你的信息,将自己的公钥发给你,模拟服务器与你通讯,此外它还可以模拟你与服务器通信,他承担一个转发的作用在客户端和服务器之间,这种模式称之为中间人。
问题:如何确保第一次请求的公钥一定是服务端的呢
4、 对称+非对称+证书
首先服务端拿着自己的公钥和个人信息去CA机构认证,CA会用自己的私钥对你提供的数据进行加密,此后客户端获取服务端公钥key,服务端直接将证书给客户端,由于客户端内置了CA的公钥则可以获取证书中包装的服务端信息,再由客户端判断是否相信此证书并建立通信。
那存不存在中间人拦截,将自己的CA发送给客户端,首先CA的公钥是全网可查的,经过CA解密后产生的数据不仅有服务端的公钥还有服务端的信息,用户需要手动确认受信任之后才可以使用改公钥传递数据。
当然不排除他人直接修改你电脑内置CA公钥,这种方式就相当于你从警察局拿了个酒驾测试机,去测试酒驾,没想到酒驾测试机是假的 (开玩笑)
5、 完整的TSL握手过程
参考:https://guisu.blog.csdn.net/article/details/8680808?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.control
简单可描述为:
- c->s : 客户端将自己支持的TLS/SSL协议版本,一个随机数、支持的对称加密算法、压缩方法发送给服务器
- s->c: 服务器保存随机数、并生成第二个随机数、选择一套加密、压缩算法,以及TLS协议版本,并将证书(域名/服务地址、公钥、证书的CA) 一同返回, 对于极度重要的信息,服务端还可以要求对客户端验证
- c->s: 客户端解析证书、若有效则生成第三个随机数作为对称加密的key,并通过CA中的公钥进行加密、并发出通知请求要求双方之后的通信都采用加密方式,将上述1,2生成的随机数 ,连同公钥加密的key等一同进行哈希计算作为此次请求的签名(防止数据被更改重发)
- s->c: 服务器通过私钥获取对称加密的key,并通过同样的方式计算哈希值,从而判断请求是否有被修改过,一切结束后服务器通知客户端通道简历完毕,之后都是加密通讯
3> Https可以防止那些问题、不能解决那些问题
解决的问题
- 在传输过程中、数据被黑客经过数据链路-ip-tcp-ssl,拿到的是加密的数据 (当然黑客在用户的电脑上做伪造的CA证书信任,也是可以做到中间人的,可参考https://segmentfault.com/q/1010000007737764)
未解决问题
- 本地用户攻击、即数据自身的加密问题,例如某人可以通过 f12查看明文的数据 (方案:数据加密 )
- 如何防止接口数据被篡改、即使是https也可以对数据做修改后再发送到服务器 (方案:数据签名)
- 重放攻击,同一个请求多次 访问 (方案:随机数+时间戳+缓存)
- 用户频繁操作 (做接口限制)