加解密与HTTPS
加密与解密
网络安全是最近几年越来越被社会和国家高层关注的问题,比如棱镜门事件、乌云网、摄像头偷拍等事件的不断曝光,也让普罗大众知道了这一阳光下的灰暗地带。
外行看热闹,内行看门道
——密码学是整个网络安全的底层支撑,就好比人离不开呼吸,没有它们,信息安全无从谈起。
密码学,顾名思义,就是研究编制密码和破译密码的学问,以前经常在谍战片中看到摩尔斯码,就是一种密码学的应用。
迄今为止,有三种不同的加密算法(以及伴生
的对应的解密算法
)。
对称加密算法
所谓对称加密算法,就是信息的收发双方事先都知道密钥和加密规则,例如,谍战片中的接头暗号和密码本就是典型的对称加密工具,它的通用过程就像下面这样。

对称加密算法有多种不同的实现方式,其中常用的是DES、3DES和AES。
DES
DES全称是Data Encryption Standard(数据加密标准)
,广泛应用于POS、ATM、收费站等金融领域。
DES是一种分组加密算法:每次处理固定长度的数据段,分组大小是64位,它的安全性依赖于混淆
与扩散
。
混淆
:隐藏任何明文同密文、或者密钥之间的关系。扩散
:使明文和密钥一起组成尽可能多的密文。
DES的关键就是从给定的初始密钥中得到16个子密钥,然后将每个子密钥按照顺序(1-16)以一系列的位操作施加于数据上,每个子密钥一次,一共重复16次,每一次迭代称之为一轮,其过程如下图。

3DES
3DES全称Triple DES(三倍DES)
,是从DES向AES过渡的算法,使用3条56位的密钥对数据进行3次加密,是DES的升级版。
3DES算法比较有意思,因为它的加密
和解密
是混在一起的。
加密过程
:加密
->解密
->加密
(不全是加密)。解密过程
:解密
->加密
->解密
(不全是解密)。
AES
AES全称Advanced Encryption Standard(高级加密标准)
,微信小程序的加密传输就是用的它。
AES的加密过程大体上可以分为字节代换
、行位移
、列混合
和轮密钥加
这几个步骤,把DES的混淆
和扩散
效果最大化。
所谓轮密钥加(AddRoundKey)
,指的是将当前轮次的轮密钥与数据块进行异或运算,将密钥信息融入到加密过程中,确保了每轮加密都使用不同的密钥,在经过多轮处理后输出密文数据。
AES也采取分组的方式,把一段话分成几段,每一段分别加密,然后再把它们拼接到一起成为密文。
而且密钥和明文一样,也会被分组,每次都将密钥中的一组数据加入到密文中执行轮密钥加(AddRoundKey)
。

非对称加密算法
和对称加密算法不同,在非对称加密算法中,信息的收发双方需要各持有两个密钥:公钥和私钥。
打一个不准确的比方,非对称加密算法有点像开保险柜
一样,柜门上的密码旋钮
(对应公钥)谁都可以看到,但除了使用拥有者的密码(对应私钥)外,理论上谁都打不开它。


常用的非对称加密算法包括RSA/DSA、ECDSA/ECC和PKCS。
RSA
RSA是一种非常常见的非对称加密算法,它的加密和解密算法也都是公开的,其运行机制用一句简单的话来说就是不可能通过公钥推导出私钥
,支付宝
的支付接口调用使用的就是它。
这种不可能通过公钥推导出私钥
的机制,是建立在大整数因子分解的困难性上的,其安全性能够抵抗目前为止已知的绝大多数密码攻击。

可以看到,如果要得到一个能够产生1024
位或2048
位二进制的质数乘积,参与运算的两个质数一定都是天文数字。
DSA
DSA和RSA的主要不同在于它不用作加密和解密,只用作签名,银行自助柜台、金融APP上的签名软件用的就是它。
DSA签名生成速度很快,但验证速度比较慢,加密时更慢,解密却很快,这一点与RSA相反,其安全性与RSA差不多。
实际上,OpenSSH7.0
及以上版本默认禁用了DSA算法。
ECC
ECC全称Elliptic curve cryptography(椭圆曲线加密)
,以太坊的比特币地址就是用它生成的,比特币椭圆曲线采用的是Secp256k1算法(y2 = x3 + 7
)。
ECC的数学基础是黎曼几何中的无穷远点性质和群率(GROUP LAW)公式。
> mkdir /home/work/ecc
> cd /home/work/ecc
# 第一步:生成私钥并输出为DER格式
> openssl ecparam -name secp256k1 -genkey > private.pem
> openssl ec -in private.pem -outform DER | tail -c +8 | head -c 32 | xxd -p -c 32 > private.der
# 第二步:生成公钥
> openssl ec -in private.pem -pubout -outform DER | tail -c 65 | xxd -p -c 65 > public.der
# 查看结果(未压缩公钥 = 前缀04 + x坐标 + y坐标,压缩公钥 = 前缀03 + x(如果y是奇数) 或 前缀02 + x(如果y是偶数))
> cat public.der
# 第三步:先SHA256,再进行RMD160运算
> openssl sha256 public.der
# 保存结果
> echo 8674a407487bb7808bbb2c1ac12603f1f3a480e98c01abbebd03477c5179f974 > public_sha256.der
# 进行RMD160运算
> openssl ripemd160 public_sha256.der
# 保存结果
> echo 9870db0ccf40cfd970b503fb031c889d089a4cd4 > public_rmd160.der
# 第四步:加上Bitcoin地址前缀(https://en.bitcoin.it/wiki/List_of_address_prefixes)
> vi public_rmd160.der
-- 在前面增加00并保存退出
9870db0ccf40cfd970b503fb031c889d089a4cd4
# 查看结果
> cat public_rmd160.der
009870db0ccf40cfd970b503fb031c889d089a4cd4
# 第五步:执行两次SHA256,取前8位作为校验和
> openssl sha256 public_rmd160.der
> echo c6349f1cb358dcd7af0dc8fd4cf7aa82293142eea7d97f45c83e86595ac22c04 > public_sha256.der
> openssl sha256 public_sha256.der
# 取前八位
> 9550d445
# 第六步:合并第四步和第五步的结果
# 第四步结果
> cat public_rmd160.der
009870db0ccf40cfd970b503fb031c889d089a4cd4
# 第五步结果
9550d445
# 结果合并
> echo 009870db0ccf40cfd970b503fb031c889d089a4cd49550d445 > public_result.der
# 第七步:执行Base59编码(这是一种独特的编码方式,是Base64的变形,主要用于比特币的钱包地址)
# 出于演示目的,仅用Base64执行编码
> openssl base64 -in public_result.der
MDA5ODcwZGIwY2NmNDBjZmQ5NzBiNTAzZmIwMzFjODg5ZDA4OWE0Y2Q0OTU1MGQ0NDUK
小常识:在比特币系统中,私钥能得公钥,公钥能得到钱包地址
,也就是私钥 -> 公钥 -> 钱包地址
,但反向是不行的。
PKCS
PKCS全称Public-Key Cryptography Standards(公钥加密标准)
,是由RSA公司设计、发布的一系列安全标准,主要用在证书申请、更新、作废、数字签名和数字信封等的创建上,目前苹果的IOS
使用的就是PKCS 12标准的证书。
> mkdir /home/work/pkcs12
> cd /home/work/pkcs12
# 第一步:生成密钥
# 生成一个1024位的私钥,保存在rsa_private_key.pem里
> openssl genrsa -out rsa_private_key.pem 1024
# 通过私钥生产公钥,保存在rsa_public_key.pem里
> openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
# 第二步:生成pkcs12文件
# 密钥库keyrepo.p12,密码123456,有效期1天
> keytool -genkey -v -alias root -keyalg RSA -storetype PKCS12 -keystore keyrepo.p12 -dname "CN=www.company.com,OU=company,O=公司,L=武汉,ST=湖北,C=中国" -storepass 123456 -keypass 123456 -validity 1
# 生成客户端证书
> keytool -genkey -v -alias p12client -keyalg RSA -storetype PKCS12 -keystore keyrepo.p12 -dname "CN=www.company.com,OU=company,O=公司,L=武汉,ST=湖北,C=中国" -storepass 123456 -keypass 123456 -validity 1
# 查看已生成的证书
> keytool -list -v -alias p12client -keystore keyrepo.p12 -storepass 123456 -storetype PKCS12
# 将p12证书导出为.cer格式
> keytool -export -alias p12client -keystore keyrepo.p12 -storetype PKCS12 -storepass 123456 -rfc -file p12.cer
# 查看.cer证书文件
> keytool -printcert -v -file /Users/bear/p12.cer
不可逆加密算法
对称加密算法和非对称加密算法在处理明文的过程中需要使用密钥,而不可逆加密算法根本就不需要,因为它压根就没想过要解密
。
这种加密算法和其他算法不同,它的解密
过程就是加密
:把明文再算一次,如果结果等于密文,就认为是解密成功。
MD5
MD5全称Message-Digest Algorithm 5(消息摘要算法5)
,是一种Hash散列算法,它可以将任意长度的字符串变换成一个128位的二进制大整数。
MD5的使用极其广泛,常用的用户密码加密就是用的它。
SHA
SHA全称Secure Hash Algorithm(安全散列算法)
,它是一系列算法的简称,有SHA-1/2/3/224/256/384/512
这一系列类别,较为常用的是SHA-2、SHA-256,早期版本的MongoDB的加密算法默认就是SHA-1,现在已经换成了SHA-2。
SHA和MD5一样,都属于Hash散列算法,将任意长度的字符串变换为长度较短、位数固定的输出序列值。
Hash散列算法是一种数学函数,它将一串数据/信息
K
通过Hash函数
进行转换/摘要
,输出另一段固定长度但更精简的数据/信息V
,作为K
的指纹
。
SSL与TLS
SSL
早在1994年,为了解决网络通信的安全风险问题,NetScape就提出了一个方案。
通过引入加密与解密技术,来杜绝偷窃问题。
通过引入信息摘要与校验和,来杜绝篡改问题。
通过引入第三方认证机构,来杜绝身份冒充问题。
于是,SSL产生了。
SSL全称Secure Sockets Layer(安全套接字层)
,是为网络通信提供安全保障及数据完整性的一种安全协议。
SSL位于TCP/IP
与各种应用层协议之间,为通讯提供安全支持,主流HTTP服务器都支持它。

SSL的基本运行过程如下。
客户端发出加密通信请求(
ClientHello
),并向服务器提供如下内容。用于会话密钥的随机数(第一个随机数)
支持的加密和压缩算法
服务器收到请求并向客户端回应(
ServerHello
)如下内容。用于会话密钥的随机数(第二个随机数)
支持的加密和压缩算法
服务器证书
请求客户端证书
客户端收到服务器回应,然后执行如下动作。
验证服务器证书,否则显示警告,选择继续或终止访问
从服务器证书中取出公钥,并向服务器发送数据
用服务器公钥加密的随机数(第三个随机数
pre-master key
)编码改变通知,开始加密会话
客户端握手结束通知(前述所有内容的Hash值,给服务端校验)
服务器收到请求并作出当前会话的最后回应(
ServerHello
)。收到第三个随机数并计算生成会话密钥,向客户端发送数据
编码改变通知,随后的信息都采用之前商定的加密方法和密钥发送
服务器握手结束通知(前述所有内容的Hash值,给客户端校验)
至此,整个握手阶段结束。

需要注意的是:在最后一步服务端收到第三个随机数并向客户端发送数据
时,以及后续的内容传输,采用的是对称加密算法,原因是效率问题。
TLS
NetScape推出了SSL,而IETF(The Internet Engineering Task Force,互联网工程任务组)将SSL扩展并制定了一系列标准之后,提出了TLS。
TLS全称Transport Layer Security(传输层安全)
,是继SSL之后的一种为保障互联网通信安全及数据完整性的安全协议,它可以说是SSL的升级版,是为了适应更广泛的应用场景。
证书
证书是什么
大学读完之后有毕业证书,并且这个证书可以在网上查询。
专业上有注会
、CCIE
、律师证
等,可以在国家职业认证机构的网站上查到。
公司注册之后,营业执照
信息也可以在网上找到。
从上述场景中,不难发现证书的三种作用。
过往经历的证明。
第三方信用担保。
唯一合法性检验。



既然证书这么有用,那能不能让它来给网站/应用撑腰
?
当然没问题,而且还诞生了一批世界著名证书颁发机构,也叫CA(Certificate Authority)证书授权中心,包括DigiCert、Comodo、GeoTrust、Symantec、RapidSSL等。
有了毕业证
,就不能没有学位证
,所以就有了不同类型的证书。
DV
:域名型证书,只需要验证域名的所有权,相当于学士学位。OV
:组织型证书,域名和组织身份都要验证,相当于硕士学位。EV
:安全性和可信任度最高,特点是浏览器有绿色地址栏,相当于博士学位。

有了学位证
,还要能够选修不同专业
:通配符型证书、单域名证书、多域名证书
和万能证书
等。
目前,所有的证书都由四部分组成。
证书的签发与验证
证书的签发过程如下。

准备证书元数据:包括签发人、地址、签发时间、有效期等,还包括证书持有者基本信息,比如DN(DNS Name)、 所有者公钥等信息
使用Hash散列算法对证书元数据进行计算,生成数字摘要。
使用签发人的私钥对该数字摘要进行加密,生成一个加密的数字摘要,也就是签发人的数字签名。
将数字签名附加到数字证书上,变成一个签过名的数字证书。
将签过名的数字证书与签发人的公钥一同发给证书使用者。
而证书的验证过程如下。

证书使用者获通过某种途径(如浏览器访问)获取到该数字证书,解压后分别获得证书元数据和数字签名。
使用同样的Hash散列算法计算证书元数据的数字摘要。
使用签发人的公钥对数字签名进行解密,得到解密后的摘要。
对比前两个步骤得到的数字摘要值,如果相同,则说明这个证书确实是被签发人验证过的合法证书,证书中的信息(最主要的是所有者的公钥)是可信的。

证书链
证书的关键在于签发人的公钥,但如果签发人本身有问题,信用差,那谁又来替TA担保呢?
就好比清北
的证书(文凭),谁来保证他们和野鸡大学不一样呢?
真实世界中有国家这个强力后盾为名牌大学做担保,在互联网里则是证书链。
以支付宝
为例,它的证书层级大概是这样的。
DigiCert Global Root CA
│
└─Secure Site CA G2
│
└─*.alipay.com
这种证书的层级结构就是证书链。
支付宝的证书层级有三个级别。
终端用户
:就是支付宝,该证书包含支付宝的公钥,支付宝的用户支付或者调用支付宝接口,就是使用这个公钥将数据加密后再传给支付宝的。中间签发人
:对公钥持有者身份的证书进行认证,负责确认确实是支付宝在使用终端用户证书,也就是负责确认支付宝确实是支付宝
,这类签发人可以有很多层级。根root
:最高级别的签发人,负责认证所有中间签发人,类似于国家教育部,认证和管理下面所有的教育机构。

也就是说,为了得到终端用户的公钥,就要得到终端用户证书;为了证明该证书可信,必须向上追溯该证书是否被中间签发人机构认证,继续线上追溯,直到找到最终的Root CA。

PKI与证书链
PKI全称Public Key Infrastructure(公钥基础设施)
,之前所说的那些内容,全都属于PKI(或者类比于教育体系)中的部分。
HTTPS
随着成本的下降,主流网站都已经开始使用HTTPS了,但有了可信机构颁发的证书,网站就真的绝对安全了吗?
HTTPS的整体过程分为证书验证
和数据传输
阶段。
证书验证阶段
数据传输阶段
当证书验证合法后,在本地生成随机数。
通过公钥加密随机数,并把加密后的随机数传输到服务端。
服务端通过私钥对随机数进行解密。
服务端通过传入的随机数构造对称加密算法,对返回结果内容进行加密后传输。
因为非对称加密算法效率很低,而实际应用场景中端与端之间通常有大量的交互,在HTTPS中只有服务端保存了私钥,因此只能实现单向的加解密,所以内容传输采用了对称加密算法。
如果没有证书颁发机构,就会出现经典的中间人攻击问题。

其实这和冒名顶替上大学如出一辙。
本地请求被
劫持
,所有请求被发送到中间人的服务器。中间人服务器返回中间人自己的证书。
客户端创建随机数,通过中间人证书的公钥对随机数加密后传送给中间人,然后凭随机数构造对称加密对传输内容进行加密传输。
中间人因为拥有客户端的随机数,可以通过对称加密算法进行内容解密。
中间人以客户端的请求内容再向正规网站发起请求。
因为中间人与服务器的通信过程是合法的,正规网站通过建立的安全通道返回加密后的数据。
中间人凭借与正规网站建立的对称加密算法对内容进行解密。
中间人通过与客户端建立的对称加密算法对正规内容返回的数据进行加密传输。
客户端通过与中间人建立的对称加密算法对返回结果数据进行解密。
之所以出现这种状况,是因为客户端不知道自己的信息被拦截了,而且客户端完全无法验证证书的真假。
用了HTTPS一样会被抓包,它只能防止用户在不知情的状态下通信被监听。
但如果用户主动信任网站,那么数据一样会被中间人
窃取,所有的安全都只是相对的,没有绝对的安全。
配置HTTPS
只要熟悉OpenSSL,是很容易创建自己的证书的,前面就用它生成过了PKCS证书。
本地HTTPS
下面用它来实现配置本地的HTTPS。
首先,用OpenSSL创建一个key.p12
证书。
> mkdir /home/work/https
> cd /home/work/https
> keytool -genkey -alias https -keyalg RSA -keysize 2048 -keystore key.p12 -validity 90

然后,创建一个在Springboot应用,并在application.properties
配置文件中加上下面的内容。
server.ssl.key-store=/home/work/https/key.p12
server.ssl.key-store-password=123456
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=https
启动服务,通过Postman访问服务接口,发现报错。
Bad Request
This combination of host and port requires TLS.
> cd /home/work/https
> openssl pkcs12 -in key.p12 -clcerts -out public_key.pem
> openssl pkcs12 -in key.p12 -nodes -out private_key.pem

接着修改Postman的配置。


再次访问Springboot服务接口,功能正常。
在线HTTPS
通过万网
、新网
、Godaddy
或其他ISP服务商
购买域名,然后再购买相关云主机。
然后购买证书,路径为:控制台
-> 产品与服务
-> SSL证书
-> SSL证书管理
-> 购买证书
。
注意:只有单域名
的DV
SSL才有免费版
(忘了什么是单域名
、什么是DV
的可以看前面)。



申请证书其实就是将刚才购买的SSL和域名绑定起来。



提交后就等待CA审核。
审核成功就可以安装到网站或APP中。
点击已签发
证书中的下载
,可以依据需要配置Tomcat或Nginx服务器证书。
Tomcat可以直接支持Springboot的运行(相关配置可百度)。
如果需要做分布式流量控制,那就必须配置Nginx服务器证书。


感谢支持
更多内容,请移步《超级个体》。