究竟什么是加密

0X00 什么不是加密

首先要先明确一个问题:我们日常使用非常多的 md5、SHA-1、SHA-256 这些 通通都不是加密,这些叫做摘要算法。一串明文经过加密算法加密之后,是可以再次解密成明文的,但是摘要算法就不行了。

拿最常见的摘要算法 md5 举例:针对任何一个合法输入,md5 都会给出一个固定长度为 128 bit(32 byte)的输出,例如 md5("hello, world") -> e4d7f1b4ed2e42d15898f4b27b019da4。准确来说你是不能通过后面这串摘要值来反推之前的原文是什么的。因为严格来说这一串摘要值可以对应无限个不同的原文。那么摘要算法一般是拿来做什么用的呢?比较常见的是用来校验数据一致性,比如鸡太美同学编写了一个程序放到网上给大家下载使用,但是我们都知道文件传输过程中理论上可能会出错,所以他在上传之前就计算了程序的 md5 并且在传到服务器上之后再次计算 md5。如果两次计算的摘要值都是正确的,那就可以证明此次数据传输没有出现错误。接下来他把摘要值贴在了下载地址旁边,每个来下载程序的人也都可以在下载之后计算摘要值以保证下载没有出错。

其实不只是防止文件传输出错,还能增加一定的安全性,比如在文件被偷换之后,可以通过计算摘要值来确定文件是不是自己想要的那个。

摘要算法既然是对任意输入都输出一个固定长度的摘要值,那么自然就会出现「撞车」事故。换句话说就是:不同的输入内容得到了相同的摘要值。具体的可以去搜索md5碰撞来查看相关资料。

更离谱的是 BASE64,它只是编码,对编码稍稍了解且有一定敏感程度的人一眼就能看出一段文本是经过 BASE64 编码的。如果你拿它「加密」的话,别人一秒钟不到就「破解」了 🤣

为什么说 BASE64 编码稍稍敏感一点的人就能看出来呢?因为 BASE64 编码过后,生成的内容是 26 个小写字母 + 26 个大写字母 + 10 个数字 + 加号 + 斜杠,总共是 64 个字符,所以被称为 BASE64。如果一大串文本全都是由混在一起的数字字母加号斜杠组成,尤其最后又追加了一两个等号的情况,那可以 99% 认为它是经过 BASE64 编码的了。

比如下面这段文字,真的很难看不出来:

1
aGVsbG8sIHdvcmxkIQ==

0X01 有哪些常见的加密方式

那么我们真正常用的加密算法是哪些呢?AES、RSA、DES、3DES、ECC 等都是比较常见的加密算法。这些算法按照加解密的密钥来看可以分为对称加密和非对称加密,这里分别简单介绍一下两种加密的特点与区别。

对称加密理解起来很简单,比如你在压缩的时候用 zip 命令设置了密码,那后面解压的时候还是要用相同的密码才可以。也就是说只有一个密钥,加密解密都用它,这种方式是我们日常使用最多的。

非对称加密则会分成两个密钥,分别是「公钥」和「私钥」。通过公钥加密的内容,只能通过私钥解密,通过私钥加密的内容也只能通过公钥解密。这样你生成一对密钥之后,将私钥保存好就可以把公钥公开出去了。别人想跟你加密通讯的话就用公钥加密内容发送给你,即使数据被别人拦截了,即使他有加密用的公钥,也无济于事。

具体非对称加密是怎么实现的,最常见的就是「超大质数相乘」。质数我们都知道,两个超级大的数相乘计算他们的积对于计算机来说是非常简单的工作。但是给一个超级大的数让你去计算它是由哪两个质数相乘得到的,就比较麻烦了。

过多解释就要涉及到数论的知识了,我比(ye)较(bu)懒(dong),所以到此为止吧。

特点 对称加密 非对称加密
密钥数量 单一密钥(加密和解密相同) 一对密钥(公钥加密,私钥解密)
速度
安全性 较低(密钥共享风险) 较高(公钥可公开)
应用场景 数据量大的加密(如文件加密) 密钥交换,数字签名(如HTTPS)
密钥管理 较难(安全地共享和管理密钥) 较易(公钥可公开分享)
示例算法 AES, DES, 3DES RSA, ECC

由于非对称加密是一个比较慢且消耗性能的操作,所以不少时候会选择用非对称加密的方式交换对称加密用的密钥,然后接下来用对称加密 🤣

这里用一个非常常见的例子来说明非对称加密:ssh 协议通过 public key 登录。我们都知道用 ssh 登录服务器的时候输入用户名密码就可以,而且还可以配置免密登录,这里的免密登录其实就是利用了非对称加密实现的。

0X02 签名?

与非对称加密一起讨论的还有签名,那签名又是什么呢?现实生活中的签名是用来表示「这些内容是我所认同的」,比如你在合同最后签上名字这种操作。计算机中的签名也是这么个用法,当你将公钥公开出去之后,就可以通过私钥加密的方式来「签名」。虽然你的公钥所有人都有,也就意味着所有人都能解密来看内容,乍一看好像跟你直接不加密也没什么大差别。但是核心就在于「公钥能解密的内容一定得是由私钥加密的」,所以这样别人就没办法伪装成你对外发送消息了。

签名的另一个用途是保障数据的一致性。假设 Alice 要给 Bob 发送一段数据,这段数据要在互联网上传输就意味着存在被篡改的可能。此时 Alice 将数据本体算一个摘要值例如 md5 出来,并将这个摘要值用私钥加密,最终追加到数据的结尾(这个就是签名),就可以了。这样一来即使这坨数据被人拦截并篡改了,篡改者也无法伪造签名,因为他没有 Alice 的私钥。最终这个数据传输给 Bob 的时候,如果 Bob 顺利通过 Alice 的公钥解密出了摘要值,再将原始数据自己算一遍摘要,如果两边对上了那就意味着数据没有被篡改。