算法名称
- RSA、DSA、ECC 非对称加密(公钥加密, 私钥解密)
- AES、DES 对称加密(密文可通过秘钥还原成原始数据)
- CRC32、MD5、SHA1 摘要算法(加签)
CRC32Cyclic Redundancy Check,又称循环冗余校验,类似还有CRC64(出现碰撞的概率小),常用于校验网络上传输的文件MD5Message-Digest Algorithm 5,又叫摘要算法和哈希算法SHA1Secure Hash Algorithm,又叫安全散列算法- 区别
- CRC的计算效率很高;MD5和SHA1比较慢
- CRC一般用作通信数据的校验(毕竟效率高适用于通信数据校验)或数据库索引;MD5和SHA1用于安全(Security)领域,比如文件校验、数字签名等
- 国密算法
| 算法类型 | 国密算法 | 类似的国际算法 |
|---|---|---|
| 公钥加密 | SM2 | RSA、ECC |
| 摘要算法 | SM3 | SHA-256 |
| 对称加密 | SM4 | AES-128 |
- 数据特征样例
- 明文: Hello, 你好
- Hex(16进制数, 可解密): 48656c6c6f2c20e4bda0e5a5bd
- Base64(可解密): SGVsbG8sIOS9oOWlvQ==
- SHA1(无法解密): b14dfdb172b5d329d7dab3454461936e6bc576a8
- SHA256(无法解密): 5b7068e7c52ee83a61de877e832841c8e39c512353618900f2e0ca3813b67784
- MD5(16位, 可小写, 无法解密): 3397650EC2C3E0F1
- MD5(32位, 可小写, 无法解密): A1EDFA063397650EC2C3E0F1DA84CB58
- AES/DES(假设密钥为123, 可解密, 多次加密结果不一样): U2FsdGVkX19bGwuDdngjwBedkOCu0RLpYyNWmYz5yAQ=
- URL编码(可解密): Hello,%20%E4%BD%A0%E5%A5%BD
加密相关的概念
对称加密- 这是加密文件常用的方式,加密的时候输入一个密码,解密的时候也用这个密码,加密和解密都用同一个密码,所以叫对称加密。常见的算法有AES、
3DES
- 这是加密文件常用的方式,加密的时候输入一个密码,解密的时候也用这个密码,加密和解密都用同一个密码,所以叫对称加密。常见的算法有AES、
非对称加密- 非对称加密有两个不一样的密码,一个叫私钥,另一个叫公钥,用其中一个加密的数据只能用另一个密码解开,用自己的都解不了,也就是说用公钥加密的数据只能由私钥解开,反之亦然
- 私钥一般自己保存,而公钥是公开的,同等加密强度下,非对称加密算法的速度比不上对称加密算法的速度,所以非对称加密一般用于数字签名和密码(对称加密算法的密码)的交换。常见的算法有
RSA、DSA、ECC
摘要算法- 摘要算法不是用来加密的,其输出长度固定,相当于计算数据的
指纹,主要用来做数据校验,验证数据的完整性和正确性。常见的算法有MD5、SHA1、SHA256、CRC
- 摘要算法不是用来加密的,其输出长度固定,相当于计算数据的
数字签名- 数字签名就是 “非对称加密+摘要算法”,其目的不是为了加密,而是用来防止他人篡改数据
- 其核心思想是
- 比如A要给B发送数据,A先用摘要算法得到数据的指纹,然后用A的私钥加密指纹,加密后的指纹就是A的签名,B收到数据和A的签名后,也用同样的摘要算法计算指纹,然后用A公开的公钥解密签名,比较两个指纹,如果相同,说明数据没有被篡改,确实是A发过来的数据
- 假设C想改A发给B的数据来欺骗B,因为篡改数据后指纹会变,要想跟A的签名里面的指纹一致,就得改签名,但由于没有A的私钥,所以改不了,如果C用自己的私钥生成一个新的签名,B收到数据后用A的公钥根本就解不开
SSL/TLS
介绍
SSL(Secure Sockets Layer)和TLS(Transport Layer Security)的关系就像windows XP和windows 7的关系,升级后改了个名字而已- TLSv1是建立在SSLv3.0之上的,可以理解成SSLv3.1,中间还有TLSv1.1,目前一般推荐使用TLSv1.2,但是最新版本已近到了TLSv1.3
- 具体使用得TLS协议版本有客户端优先选择,但是服务器可设置支持的协议版本。像XP系统下的谷歌(v49)就不支持TLSv1.2,但是XP系统下的火狐浏览器是支持的
- 最初的SSL只支持TCP,现在已经可以支持UDP
HTTPS=HTTP+TLS、FTPS=FTP+TLS。SSH和SSL/TLS是两个不同的协议,SSH并不依赖于SSL/TLS- 测试https访问
https://www.ssllabs.com/ssltest/analyze.html?d=test.aezo.cn
证书概念
私钥:私钥就是一个算法名称加上密码串,自己保存,从不给任何人看公钥:公钥也是一个算法名称加上密码串,一般不会单独给别人,而是嵌在证书里面一起给别人CA:专门用自己的私钥给别人进行签名的单位或者机构申请签名文件:在公钥的基础上加上一些申请人的属性信息,比如我是谁,来自哪里,名字叫什么,证书适用于什么场景等的信息。然后带上进行的签名,发给CA(私下安全的方式发送),带上自己签名的目的是为了防止别人篡改文件证书文件:证书由公钥加上描述信息,然后经过私钥签名之后得到。一般都是一个人(一般是CA)的私钥给另一个人的公钥签名;如果是自己的私钥给自己的公钥签名,就叫自签名- 签名过程
- CA收到申请文件后,会走核实流程,确保申请人确实是证书中描述的申请人,防止别人冒充申请者申请证书,核实通过后,会用CA的私钥对申请文件进行签名
- 签名后的证书包含:申请者的基本信息,CA的基本信息,证书的使用年限,申请人的公钥,签名用到的摘要算法,CA的签名
- 签完名之后,证书就可以用了
- 证书找谁签名合适
- 别人认不认你的证书要看上面签的是谁的名,所以签名一定要找权威的人来签,否则别人不认,哪谁是权威的人呢?那就是CA,哪些CA是受人相信的呢?那就要看软件的配置,配置相信谁就相信谁,比如浏览器、操作系统等,安装好了之后里面就内置了很多信任的CA的证书,只要是那些CA签名的证书,操作系统/浏览器都会相信。而自己写的程序,可以由你自己指定信任的CA(即使用自签名证书);浏览器使用自签名证书时必须将CA证书添加为信任的证书,否则会有警告
- 那么CA的证书又是谁签的名呢?一般CA都是分级的,CA的证书都是由上一级的CA来签名,而最上一级CA的证书是自签名证书
- 以浏览器为例,说明证书的验证过程
- 在TLS握手的过程中,浏览器得到了网站的证书
- 打开证书,查看是哪个CA签名的这个证书
- 在自己信任的CA库中,找相应CA的证书
- 用CA证书里面的公钥解密网站证书上的签名,取出网站证书的校验码(指纹),然后用同样的算法(比如sha256)算出出网站证书的校验码,如果校验码和签名中的校验码对的上,说明这个证书是合法的,且没被人篡改过
- 读出里面的CN,对于网站的证书,里面一般包含的是域名
- 检查里面的域名和自己访问网站的域名对不对的上,对的上的话,就说明这个证书确实是颁发给这个网站的
- 到此为止检查通过
- 如果浏览器发现证书有问题,一般是证书里面的签名者不是浏览器认为值得信任的CA,浏览器就会给出警告页面,这时候需要谨慎,有可能证书被掉包了。如访问12306网站,由于12306的证书是自己签的名,并且浏览器不认为12306是受信的CA,所以就会给警告,但是一旦把12306的根证书安装到了你的浏览器中,那么下次就不会警告了,因为配置了浏览器让它相信12306是一个受信的CA
TLS握手过程
1 | +--------+ +--------+ |
证书生成示例
1 | mkdir cert && cd cert |
- openssl参数说明
-newkey rsa:2048:生成一个长度为2048的采用RSA算法的私钥-nodes:这个私钥在本地存储的时候不加密(可以通过其它参数来加密私钥,这样存储比较安全)-sha256:生成的证书里面使用sha256作为摘要算法-keyout ca.key:输出私钥到ca.key(或者取名key.pem)-x509:证书文件格式为x509,目前TLS默认只支持这种格式的证书-days 365:证书有效期1年-out ca.crt:生成的证书文件保存到ca.crt(或者取名cert.pem)
- 证书文件
- 证书的CRT内容:”—–BEGIN CERTIFICATE—–”开头,”—–END CERTIFICATE—–”结尾
- 证书的私钥内容:”—–BEGIN PRIVATE KEY—–”开头,”—–END PRIVATE KEY—–”结尾
- 证书生成填写
1 | Country Name (2 letter code) [XX]:CN |
HTTPS
- 证书检测在线工具 可以查看包括二级证书
- 使用 HTTPS 时,所有的 HTTP 请求和响应数据在发送到网络之前,都要进行加密。网络分层如下

- 不使用SSL/TLS的HTTP通信,就是不加密的通信。所有信息明文传播,会有以下风险
- 窃听风险(eavesdropping):第三方可以获知通信内容
- 篡改风险(tampering):第三方可以修改通信内容
- 冒充风险(pretending):第三方可以冒充他人身份参与通信
- SSL 是个二进制协议,与 HTTP 完全不同,其流量是承载在另一个端口上的(SSL 通常是由端口 443 承载的)
- 如果URL的方案为http,客户端会打开服务器80端口的连接
- 如果URL的方案为https,客户端就会打开一条到服务器端口443(默认情况下) 的连接,然后与服务器“握手”,以二进制格式与服务器交换一些 SSL 安全参数, 附上加密的 HTTP 命令
- 服务器公钥放在服务器的数字证书之中
- 清除谷歌证书缓存:访问
chrome://net-internals/#hsts,在Delete domain security policies中输入域名删除证书,然后重新打开浏览器
Let’s Encrypt免费证书使用
- 在线申请证书:https://www.sslforfree.com/
- 基于certbot自动获取证书:可实现通配符证书
- 基于acme.sh:证书申请脚本和续签脚本 https://github.com/acmesh-official/acme.sh
申请Lets证书(基于certbot)
Linux安装和自动更新证书
- 简单测试(建议参考下文: 结合自动验证DNS脚本进行配置) ^3
1 | ## 安装 |
- 结合自动验证DNS脚本进行配置通配符证书(阿里云需要AccessKey账号)(2403)
1 | ## 参考:https://www.cnblogs.com/trblog/p/14690908.html |
- 手动配置nginx证书
1 | server { |
- 设置到期7天前进行续期(默认是30天), 创建脚本
certbot-renew.sh(执行使用certbot-renew.sh example.com)
1 |
|
- 测试https访问
https://www.ssllabs.com/ssltest/analyze.html?d=test.aezo.cn - 常见错误
Invalid response from https://dnspod.qcloud.com/static/webblock.html?d=xxx尽管已经备案也被拦截了(特别是换成腾讯DNS专业版之后出现)- 可以换成DNS验证解决,参考: https://zhiqiang.org/it/letsencrypt-and-nginx-set-https.html
Windows安装
- Certbot 已于 2024 年 2 月停止对 Windows 的支持
- v2.9.0
- Windows 10以上基于 WSL
Linux申请Lets证书(基于acme.sh)
1 | # 参考:https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E |
Windows申请Lets证书(基于win-acme)
- 基于win-acme,下载win-acme.v2.2.9.1701.x64.trimmed.zip
- 参考: https://blog.csdn.net/vasing_/article/details/148135054
- 生成证书操作流程
- 执行wacs.exe文件
- Create new cerificate (full options)
- Manual input
- 输入host name (即需要认证的域名)
- 选择默认认证方式
[http-01] Save verification files on (network) path通过路径验证(需提前配置.well-known验证路径,参考下文,此时只能配置 80端口,先不要配置 443端口)- 当提示输入 Path: (网站根路径) 时,输入下文 nginx 配置中指定的 root 目录路径 (例如 D:/path/to/newdomain_webroot)
serve verification files from memory通过内存验证服务器(需要在实际服务器上运行上述exe。会先访问Lets自动提交工单,然后Lets会访问配置的域名,会在内存生成一个随机码进行验证。需保证 80 端口不被占用)[dns-01] Create verification records manually (auto-renew not possible)基于DNS进行验证(可在工作机上运行上述exe。选择后继续往下操作,最后会生成一个DNS解析值;如生成test.aezo.cn的证书,则他需要解析出一个 _acme-challenge.test,类型为TXT,值为随机生成的一串字符;解析好后,稍等片刻等域名解析生效后再继续执行后续步骤进行验证)
- rsa key
- pem encoded files(Apache, nginx, etc.)
- 输入文件存放路径(需提前创建)
- 最终会生成类似 newdomain.example.com-chain.pem (完整证书链, 对应 ssl_certificate) 和 newdomain.example.com-key.pem (私钥, 对应 ssl_certificate_key)
- No store steps
- 输入通知邮箱
- 输入 y 打开协议文件
- 输入 y 同意协议
- 将生成的文件设置到nginx(参考上文手动配置nginx证书)
- 查看托管的证书
- 再次执行wacs.exe文件
- A: Manage renewals (1 total) 可查看托管的自动更新证书
- 路径验证nginx配置
1 | server { |
证书过期导致RestTemplate(SpringBoot)访问接口失败
- 报错:unable to find valid certification path to requested target
- 自定义RestTemplate同时支持访问http与https
1 |
|
SM国密算法
- Java可使用 Bouncy Castle(开源加密库,支持 SM 系列)
- 国密算法类型
- SM2:基于椭圆曲线密码学的公钥算法(非对称)
- SM3:安全散列算法(类似 SHA-256)
- SM4:对称加密算法(类似 AES)
- 参考: http://www.yiim.net/gmc/
- 引入Bouncy Castle
1 | <dependency> |
- 案例
1 | import org.bouncycastle.asn1.gm.GMNamedCurves; |
AES/DES
简介
- 密码学中的高级加密标准 (Advanced Encryption Standard,
AES),又称高级加密标准Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。高级加密标准已然成为对称密钥加密中最流行的算法之一。该算法为比利时密码学家Joan Daemen和VincentRijmen所设计,结合两位作者的名字,以Rijndael命名之 [1] - 加密方式如
AES/CBC/NOPaddingAES/CBC/PKCS5Padding128位(16字节),jdk默认支持,建议使用AES/CBC/PKCS7Padding256位(32字节),jdk默认不支持
- 说明
- 类似有
DES/CBC/PKCS5Padding - 上述命名意义分别为:AES为算法名称,CBC为加密模式,PKCS5Padding为填充方式(PKCS5Padding是PKCS7Padding在填充块大小为8个字节时的特殊情况,本质上是一样的)
- 使用CBC模式,需要一个向量iv,可增加加密算法的强度
- 一般在对内容加密时,需要先将内容进行编码,如Base64。因为,不是所有的字节数组都可以new String(),然后在通过String.getBytes()还原
- 类似有
JAVA 实现
java默认不支持PKCS7,如果非要指定PKCS7需要借助
BouncyCastle类和安装扩展包BouncyCastle类1
2
3
4
5
6
7<!-- AES/CBC/PKCS7Padding 加解密 -->
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.55</version>
</dependency>安装扩展包
- oracle官方下载(JDK1.8)
- 下载之后得到
local_policy.jar,US_export_policy.jar两个jar包,把这两个jar包放到jre/lib/security目录下替换原来的两个jar包即可 - 如果是128位(16字节)则无需安装扩展包
- 示例(基于jdk1.8测试)
1 | import org.apache.tomcat.util.codec.binary.Base64; |
JS 实现
- 基于插件
CryptoJS - 参考
SHA1
1 | public static String sha1(String str) |
Hex(16进制)
1 | import org.bouncycastle.util.encoders.Hex; |
参考文章
