SSL 证书入门:概念、签发与本地 HTTPS

SSL(现代行业标准通常称为 TLS)是一套安全协议,SSL 证书就是基于该协议的数字证书,核心作用:加密互联网传输流量、校验服务器真实身份。

SSL 全称为安全套接字层,能够在 Web 浏览器与 Web 服务器之间建立加密通信链路。部署 SSL 证书之后网站就可以使用 HTTPS 协议。SSL 证书是存放在网站源服务器上的数据文件。

什么是 HTTPS?

超文本传输协议安全(HTTPS)是 HTTP 的安全版本,HTTP 是浏览器与网站之间传输数据的基础协议,HTTPS 在其基础上增加加密能力保障传输安全。

在传输登录账号、密码、个人隐私、医疗保险等敏感业务数据场景下,HTTPS 的加密能力尤为重要。 现代 Web 最佳实践建议所有网站都启用 HTTPS,需要登录鉴权的网站更是必须使用。

现代浏览器会对 HTTP、HTTPS 做差异化标记:连接安全时,地址栏会给出安全连接提示(旧版常见为挂锁图标)。Chrome 等主流浏览器会将未启用 HTTPS 的网站标记为不安全。

SSL 证书是如何工作的?

一份 SSL 证书数据文件内包含以下信息:

  • 针对其颁发证书的域名
  • 证书颁发给哪一个人、组织或设备
  • 证书由哪一证书颁发机构颁发
  • 证书颁发机构的数字签名
  • 关联的子域
  • 证书的颁发日期
  • 证书的到期日期
  • 公钥(私钥为保密状态)

密码学说明:SSL 使用非对称加密机制,使用公钥加密的数据只能使用配套私钥解密。公钥放置在证书内对外公开,私钥必须严格保密,不能对外泄露

证书部署在网站源服务器,浏览器访问网站的时候服务器会将证书下发给访问设备。

大部分浏览器支持查看证书详情:Chrome 浏览器点击地址栏左侧挂锁图标,即可查看完整证书信息。

如何获取 SSL 证书?

想要证书被浏览器、操作系统信任,域名证书必须由 CA(证书颁发机构)签发。 CA 是受广泛信任的第三方机构,负责生成、颁发 SSL 证书;CA 使用自身私钥对证书进行数字签名,客户端设备通过校验签名确认证书合法性。部分 CA 机构证书服务收费,也存在免费 CA 机构(例如 Let’s Encrypt)。

证书签发完成后,需要上传并且在源站 Web 服务器完成安装激活。很多云托管平台可以代为完成证书部署。服务器证书激活成功后,网站就可以通过 HTTPS 访问,网站往返流量全部被加密保护。

什么是自签名 SSL 证书?

任何人都可以生成公私钥对,自行组装全部证书信息,制作证书,该类证书称为自签名证书。

自签名证书使用网站自身私钥完成签名,没有外部 CA 权威机构校验服务器身份

重要特性:浏览器默认不信任自签名证书;即使地址栏协议是 https,浏览器依旧标记站点不安全,极端场景浏览器直接断开网络连接,网站无法加载。

备注:为了解决浏览器信任问题,可将根证书添加到系统或浏览器的受信任根证书颁发机构。

使用范围限制:仅用于内网、本地开发测试,禁止公网生产环境直接使用自签名证书

不同类型证书的区别

区分证书不是依靠文件后缀,依靠文件实际内容与编码格式;同一份证书可以导出为多种后缀格式。

  • .pem、.key: .pem 证书文件一般是文本格式,可以存放证书或私钥,或者两者都包含。 .pem 文件如果只包含私钥,一般用 .key 文件代替。
  • .csr: 数字证书签名请求文件(Certificate Signing Request),将其提交给证书颁发机构(CA)对证书签名。
  • .der、.cer: 证书的公钥格式(证书颁发机构签名后的证书或者自签名证书,包含证书持有人的信息、持有人的公钥以及签署者的签名等信息)。文件是二进制格式,只含有证书信息,不包含私钥。
  • .crt: 证书的公钥格式。证书文件是二进制格式或文本格式,一般为文本格式,功能与 .der.cer 证书文件相同(cer 是 crt 证书的微软形式)。
  • .jks: keytool 证书工具支持的证书私钥格式。
  • .pfx、.p12:微软支持的私钥格式(.p12.pfx 的新格式)。证书文件是二进制格式,同时包含证书和私钥,且一般有密码保护;
  • .keystore、.truststore: 两者本质都是 keystore,都是储存密钥的容器。keystore 用来存储自己的公钥和私钥,而 truststore 用来存储自己信任对象的公钥。.truststore 是必须的,如果没有显式的指定,那么 Java 会默认指定为 $JAVA_HOME/lib/security/cacerts 文件。

不同语言需要的证书格式并不一致,比如:Java 采用 jks、.NET 采用 pfx 和 cer、PHP 则采用 pem 和 cer。

OpenSSL

openssl 是一个功能丰富且自包含的开源安全工具箱。

它提供的主要功能有:SSL、TLS 协议实现(早期版本还包括已废弃的 SSLv2、SSLv3)、大量软算法(对称、非对称、摘要)、大数运算、非对称算法密钥生成、ASN.1 编解码库、证书请求(PKCS10)编解码、数字证书编解码、CRL 编解码、OCSP 协议、数字证书验证、PKCS7 标准实现和 PKCS12 个人数字证书格式实现等功能。

openssl 采用 C 语言作为开发语言,这使得它具有优秀的跨平台性能。openssl 支持 Linux、UNIX、Windows、macOS 等平台。

版本提示:OpenSSL 3.x 仍可生成 PKCS#12(.p12)。若旧系统(部分 Java、Windows)无法导入,生成时需加 -legacy,以兼容较旧的加密算法。

生成根证书

根证书(root.key)

openssl genrsa -out root.key 2048
  • genrsa:产生 rsa 密钥命令。
  • -out: 输出路径。
  • 2048:密钥的长度位数(本命令已显式指定;旧版 genrsa 未指定时默认曾为 512 位)。

可查看详细解析,包含两个大素数和两个指数和一个系数:

openssl rsa -in root.key -text
Private-Key: (2048 bit, 2 primes)
modulus:
publicExponent: 65537 (0x10001)
privateExponent:
prime1:
prime2:
exponent1:
exponent2:
coefficient:
writing RSA key
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----

也可通过命令提取公钥:

openssl rsa -pubout -in root.key
writing RSA key
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----

根证书请求文件(root.csr)

openssl req -new -out root.csr -key root.key -keyform PEM
Country Name (2 letter code) [AU]:cn
State or Province Name (full name) [Some-State]:zj
Locality Name (eg, city) []:hz
Organization Name (eg, company) [Internet Widgits Pty Ltd]:lizhao
Organizational Unit Name (eg, section) []:lizhao
Common Name (e.g. server FQDN or YOUR name) []:app.xxx.com
Email Address []:1927344728@qq.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:lizhao
  • CSR:Certificate Signing Request 英文缩写,即证书请求文件。
  • req:产生证书签发申请命令。
  • -new:新请求。
  • -out:输出路径。
  • -key:密钥是 root.key 文件。
  • -keyform PEM:证书有 pem 和 der 格式之分。pem 为文本编码,常见于 Nginx、Apache、Node;der 为二进制编码。

签发根证书(root.cer)

openssl x509 -req -in root.csr -out root.cer -signkey root.key -CAcreateserial -days 3650
Warning: ignoring -CAcreateserial option since -CA option is not given
Certificate request self-signature ok
subject=C=cn, ST=zj, L=hz, O=lizhao, OU=lizhao, CN=lizhao, emailAddress=1927344728@qq.com
  • x509:签发 X.509 格式证书命令
  • -req:表示证书输入
  • -in:表示输入文件。
  • -out:表示输出文件。
  • -signkey:表示自签名。
  • -CAcreateserial:创建证书序列号,使用此选项,当 CA 序列号文件不存在时将被创建。它将包含序号“02”,正在签名的证书将具有 1 作为其序列号。通常如果指定了 -CA 选项并且序列号文件不存在,则会出现错误。
  • -days:表示有效时间。部分校验场景对过长有效期更严格,自签根证书用 3650 天一般仍可用。

生成 p12 格式证书

openssl pkcs12 -export -out root.p12 -inkey root.key -in root.cer

生成服务端证书

# 服务器私钥(server.key)
openssl genrsa -out server.key 2048

# 服务端请求文件(server.csr)
openssl req -new -out server.csr -key server.key -keyform PEM

# 注意:Windows 下,'/' 会被解析为路径
openssl req -new -out server.csr -key server.key -keyform PEM -subj /C=cn/ST=zj/L=hz/O=lizhao/OU=lizhao/CN=lizhao/emailAddress=1927344728@qq.com

# 使用根证书签发服务器证书(server.cer)
openssl x509 -req -in server.csr -out server.cer -CA root.cer -CAkey root.key -CAcreateserial -days 365

生成客户端证书

# 客户端私钥(client.key)
openssl genrsa -out client.key 2048

# 客户端请求文件(client.csr)
openssl req -new -out client.csr -key client.key -keyform PEM

# 使用根证书签发客户端证书(client.cer)
openssl x509 -req -in client.csr -out client.cer -CA root.cer -CAkey root.key -CAcreateserial -days 365

# 生成客户端 p12 格式证书
openssl pkcs12 -export -clcerts -in client.cer -inkey client.key -out client.p12

证书格式转换

# 转 P12(下文 `.crt` 与上文 `.cer` 为同类证书公钥文件,按实际文件名替换即可)
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "client" 

# crt 转 pem
openssl x509 -in client.crt -out client.pem -outform PEM

# crt 转 cer
openssl x509 -in server.crt -out server.cer -outform der
openssl x509 -in client.crt -out client.cer -outform der

# 转 der
openssl x509 -in client.crt -outform der -out client.der

# 测试证书命令
curl --cacert root.crt --cert client.crt --key client.key --tlsv1.2 --insecure https://aaa.xxx.cn/api/bbb

keytool

Keytool 是一个 Java 数据证书的管理工具,Keytool 将密钥(key)和证书(certificates)存在一个称为 keystore 的文件中。 在 JDK 1.4 以后的版本自带 keytool,位于:%JAVA_HOME%\bin\keytool.exe

# 生成签名证书
keytool -genkey -alias client -keyalg RSA -keysize 2048 -validity 36500 -keystore client.keystore

# 查看证书
keytool -list -v -keystore client.keystore

# .keystore 转 .p12
keytool -importkeystore -srckeystore client.keystore -srcstoretype JKS -deststoretype PKCS12 -destkeystore client.p12

# .p12 转 .jks
keytool -v -importkeystore -srckeystore client.p12 -srcstoretype PKCS12 -destkeystore client.jks -deststoretype JKS

# .jks 转 .pem
keytool -export -rfc -keystore client.jks -alias client -file client.pem
keytool -genkey -alias server -keyalg RSA -keysize 2048 -validity 36500 -keystore server.keystore

keytool -importkeystore -srckeystore server.keystore -srcstoretype JKS -deststoretype PKCS12 -destkeystore server.p12

keytool -v -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore server.jks -deststoretype JKS

keytool -export -rfc -keystore server.jks -alias server -file server.pem

mkcert

mkcert 是一个使用 Go 语言编写的生成本地自签证书的小程序,具有跨平台、使用简单、支持多域名、自动信任 CA 等一系列方便的特性,仅供本地开发环境快速搭建 HTTPS,禁止公网生产环境使用

安全警告:mkcert 生成的 rootCA-key.pem 拥有劫持本机全部 HTTPS 请求的能力,切勿分享、外泄该私钥文件。

安装

不同操作系统安装方式,参考官方仓库,下面为常用方式。

macOS

brew install mkcert
brew install nss # 适配 Firefox 浏览器

Linux(Debian、Ubuntu)

sudo apt install libnss3-tools
# 二进制包安装
curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64"
chmod +x mkcert-v*-linux-amd64
sudo cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert

Windows(Chocolatey)

choco install mkcert

使用命令

mkcert 规避了繁杂的 openssl 命令,几个简单的参数就可以生成一个本地可信的 HTTPS 证书了。

# 将 mkcert 使用的根证书加入了本地可信 CA
mkcert -install

# 生成自签证书
mkcert localhost 127.0.0.1 ::1

Node 不会读取系统根信任库,使用 mkcert 证书的 Node 项目,需要设置环境变量指定 CA 文件:

export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"

移动端设备使用:需要拿到 mkcert -CAROOT 输出路径下的 rootCA.pem,在手机手动安装根证书,移动端访问本地 HTTPS 服务才会信任证书。

高级参数示例:

# 指定输出证书、私钥文件名
mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1

# 使用 ecdsa 椭圆曲线密钥生成证书
mkcert -ecdsa localhost

# 输出 pkcs12 格式
mkcert -pkcs12 localhost

# 根据已有 csr 请求文件生成证书
mkcert -csr xxx.csr

查看 CA 根证书存放路径

mkcert -CAROOT

环境变量 CAROOT 可以自定义 mkcert 存放 CA 证书目录;TRUST_STORES 环境变量可以限定需要写入的信任存储。

如何使用证书?

Node.js 中使用

const fs = require("fs")
const express = require("express")
const https = require("https")
const app = express()
const server = https.createServer({
    key: fs.readFileSync('./clientKey.pem'),
    cert: fs.readFileSync('./clientCert.pem')
}, app).listen(9601, () => {
    console.log('本地安全链接:https://localhost:9601')
})

webpack 中使用

通常启动本地服务是通过 http://localhost 来访问的,这在目前普遍使用 HTTPS 协议的情况下,可能会遇到一些问题。比如:无法访问 HTTPS 保护服务器,或者可访问,但限制了 Cookie 发送(iOS)。

module.exports = {
    devServer: {
        https: true,
        key: fs.readFileSync('./clientKey.pem'),
        cert: fs.readFileSync('./clientCert.pem')
    }
}

实测: 可以用 https://localhost:9601 访问,但无法用 https://0.0.0.0:9601 或者本地 IP 访问,Chrome 中报错:net::ERR_CERT_INVALID

备注:webpack-dev-server 4+ 将 https: true 调整为 server: { type: 'https', options: { key, cert } },配置时按所用版本选择。

uni-app 中使用

uni.configMTLS({
    certificates: [{
        'host': 'www.test.com',
        'client': '/static/client.p12',
        'clientPassword': '123456789',
        'server': ['/static/server.cer'],
    }],
    success ({code}) {
        console.log(code)
    }
});

相关问题

如何让 Mac 信任证书?

如果要生成让 Mac 信任自签名的证书,需要先让 Mac 信任根证书,再为本地开发环境颁发证书。

让 Mac 信任根证书,以便它所发布的所有单个证书也是可信的:启动台 -> 搜索输入“钥匙串” -> 单击,在钥匙串访问窗口,文件 -> 导入项目 导入生成的 .pem 文件。双击导入的证书,并在 『信任』部分中将 『使用此证书时:』下拉列表更改为 『始终信任』 。

只需要信任根 CA 证书,由该根证书签发的业务服务证书,系统会自动信任。

参考资料

OpenSSL 中文手册

mkcert 官方仓库

什么是 SSL 证书?

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-08-24 22:03:48

results matching ""

    No results matching ""