最近项目在配 HTTPS,又在弄什么证书,想着自己也弄一下吧
1. OpenSSL
OpenSSL 是一个实现加密和认证的软件,而OpenSSH 是实现 SSH 远程安全登录的软件(其安全功能借用了OpenSSL),其提供秘钥证书管理、对称加密和非对称加密等功能
常用参数如下:
- -new:表示生成一个新证书签署请求
- genrsa:生成私钥
- rsa:提取公钥
- req:生成证书请求
- x509:用于签署证书请求文件、生成自签名证书、转换证书格式等等的一个公钥基础设施
首先来了解下非对称加密,然后再看 HTTPS 的流程,最后举例使用
2. 非对称加密
pem 是一种 Base64 编码的消息传输编码语法(还有der 语法), PKSC1,PKSC12 这些是证书的内部的存储结构方式
Base64 防止不可见字符在传输过程中不同设备对其不同处理导致传输结果不同(只包含英文、数字、+、/)
2.1 默认无密码方式
openssl 默认采用 pem 语法,PKSC1格式存储、注意 Java 是需要 PKSC12、JKS 格式才能使用,转换格式(公钥无需转换)
# 生成私钥
$openssl genrsa -out private.pem 1024
# PKSC1 格式转成 pkcs8
$openssl pkcs8 -topk8 -inform PEM -in private.pem -outform pem -nocrypt -out private-pkcs8.pem
# pkcs8 格式转成 PKSC1
$openssl rsa -in private-pkcs8.pem -out private.pem
# 提取公钥
$openssl rsa -in private.pem -pubout -out public.pem
私钥后缀常用 xxx.pem 或者 xxx.key,这里容易混淆
2.2 指定加密算法加密码
# 生成私钥
$openssl genrsa -aes256 -out rsa_aes_private.key 2048
# 提取公钥
$openssl rsa -in rsa_aes_private.key -pubout -out rsa_aes_public.key
# 转换格式
$openssl pkcs8 -topk8 -inform PEM -in rsa_aes_private.key -outform PEM -nocrypt -out rsa_aes_private_pkcs8.key
2.3 Java 生成密钥对
public class Test {
public static void main(String[] args) throws NoSuchAlgorithmException {
// 密钥对生成器
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair keyPair = keyGen.generateKeyPair();
byte[] privateKey = keyPair.getPrivate().getEncoded();
byte[] publicKey = keyPair.getPublic().getEncoded();
System.out.println(base64Encode(privateKey));
System.out.println(base64Encode(publicKey));
}
// Base64 编码
static String base64Encode(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
}
2.4 非对称加密 RAS 算法原理
利用大整数因式分解困难、大素数乘积欧拉函数复杂的特点来保证钥匙的安全性
流程:
- 随机找两个大质数 p、q
- 算出两质数的乘积 n
- 算出质数乘积的欧拉函数 φ(n) (互质数复杂性:(p-1)(q-1) )
- 随机选择一个 φ(n) 的互质数 e
- 根据 e 和 φ(n) 找出其中一个模反元素 d (二元一次方程,d众多解)
- n 和 e 封装成公钥,其余不公开
- n 和 d 封装成密钥
安全性在于:知道公钥(n、e)也解不出密钥所需的 d:
- d 源于模反,所以得知道e 和 φ(n) 才有解,而e在公钥中已知,只需知道 φ(n) 即可
- φ(n) = (p-1)(q-1),得知道两个质数才行,n 在公钥中已知
- n = p * q,(目前因式分解无解,安全性在此)
2. HTTPS 流程
3. 证书
3.1 名词解释
- PKC:公钥证书,简称证书。cer证书只包含公钥信息,提供给客户端使用
- CA:认证机构,对证书进行管理
- PKI:公钥基础设施,是为了更高效地运用公钥而制定的一系列规范和规格的总称(有PKCS、X509)
- x509证书:一般会用到三类文件,key,csr,crt
- Key:私用密钥,openssl格式,通常是rsa算法
- csr:是证书请求文件,用于申请证书。制作csr文件时,必须使用自己的私钥来签署申请,还可以设定一个密钥
- crt:CA认证后的证书文件(windows下面的csr,其实是crt),签署人用自己的key给你签署的凭证
3.2 准备
查看 OpenSSL 默认配置,需将下面生成的文件放入对应的目录下。或者自行创建所需文件
# 查看版本全部信息
openssl version -a
# 配置文件地址
# OPENSSLDIR: "/etc/pki/tls"
# 配置文件内容
touch /etc/pki/CA/index.txt 生成证书索引数据库文件
echo 01 > /etc/pki/CA/serial 指定第一个颁发证书的序列号
3.3 CA
CA 机构需要生成根证书,即自签名的证书
# 生成 CA 的私钥
openssl genrsa -out ca.key 2048
# 生成 CA 的自签证书
openssl req -new -x509 -key ca.key -out ca.crt
3.4 Server
服务器端需要将自己的证书请求交给 CA 机构签署来生成服务器端证书文件
# 私钥
openssl genrsa -out server.key 2048
# 生成证书请求文件(有公钥信息)
# Common Name (eg, YOUR name) []:192.168.1.246 一定要写服务器所在的ip地址
openssl req -new -key server.key -out server.csr
# 将服务器的证书请求文件交给 CA 机构签署,生成x509格式证书
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
# 将证书转成 Java 支持的.p12格式
openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.pfx
也可生成 Client 证书(用于双向认证)
3.5 示例
客户端(Chrome)安装 ca.crt,服务器端指定 server.crt(服务器端用 SpringBoot 测试)
server:
port: 8443
ssl:
enabled: true
key-store: classpath:server.pfx
key-store-password: xxx
keyStoreType: PKCS12