一、CA 概述

1. 什么是 CA

CA 即 Certificate Authority,中文名为证书颁发机构,它是负责管理和签发数字证书的第三方机构。在网络通信中,由于存在各种安全风险,需要一种机制来确保通信双方的身份真实性以及数据传输的安全性,CA 就承担了这样的角色。

2. CA 的作用

  • 身份验证:CA 通过验证申请者的身份信息,为其颁发数字证书。数字证书就像是网络世界中的身份证,包含了申请者的身份信息(如组织名称、个人姓名等)以及公钥等内容。当通信双方进行交互时,可以通过验证对方的数字证书来确认其真实身份。
  • 数据加密:数字证书中包含公钥,公钥可以用于加密数据。只有持有与之对应的私钥的一方才能解密数据,从而保证了数据在传输过程中的保密性。
  • 防止中间人攻击:在没有 CA 的情况下,攻击者可能会伪装成合法的通信方,截取并篡改数据。CA 颁发的数字证书可以有效防止这种情况的发生,因为只有合法的证书持有者才能使用正确的私钥进行解密和签名操作。

3. CA 的应用

1. 网站安全通信(HTTPS)

  • 原理:CA 为企业网站颁发 SSL/TLS 证书,当用户访问企业网站时,浏览器会验证网站的证书是否由受信任的 CA 颁发。如果验证通过,浏览器与网站之间将建立起加密的 HTTPS 连接,确保数据在传输过程中的保密性和完整性。
  • 应用场景:企业的官方网站、电子商务平台、在线支付系统等都需要使用 HTTPS 来保护用户的敏感信息,如用户名、密码、信用卡号等。通过使用 CA 颁发的证书,企业可以增强用户对网站的信任,减少信息泄露和中间人攻击的风险。

2. 虚拟专用网络(VPN)

  • 原理:在企业的 VPN 连接中,CA 可以用于验证 VPN 服务器和客户端的身份。VPN 服务器和客户端都需要安装由 CA 颁发的证书,在建立连接时,双方会互相验证对方的证书,只有证书验证通过后,才会建立安全的 VPN 隧道。
  • 应用场景:企业员工在远程办公时,需要通过 VPN 连接到企业内部网络。使用 CA 证书可以确保只有经过授权的员工才能访问企业内部资源,同时保护数据在传输过程中的安全。

4. 公钥、私钥、证书

基本概念

  • 公钥(Public Key):公钥是公开的密钥,是由密钥对生成算法生成的一对密钥中的一个。公钥可以自由地分发给需要与密钥所有者进行通信的其他方。公钥主要用于加密数据和验证数字签名。
  • 私钥(Private Key):私钥是保密的密钥,与公钥成对生成,必须严格保密,只有密钥所有者才能持有。私钥主要用于解密用其对应的公钥加密的数据,以及创建数字签名。
  • 证书(Certificate):证书也称为数字证书,是由证书颁发机构(CA)签发的一种电子文档,它将公钥与实体(如个人、组织、服务器等)的身份信息绑定在一起。证书的作用是证明公钥的所有者身份的真实性和合法性。

公钥私钥之间的关系

  • 成对生成:公钥和私钥是通过特定的密码学算法(如 RSA、ECC 等)同时生成的一对密钥。这对密钥在数学上是相互关联的,但从公钥无法推导出私钥,保证了私钥的安全性。
  • 加密和解密:使用公钥加密的数据只能由对应的私钥解密。例如,当 A 要向 B 发送保密信息时,A 可以使用 B 的公钥对信息进行加密,然后将加密后的信息发送给 B。B 收到加密信息后,使用自己的私钥进行解密,从而获取原始信息。这种加密方式确保了信息在传输过程中的保密性,因为只有持有私钥的 B 才能解密信息。
  • 签名和验证:私钥可以用于创建数字签名,公钥用于验证数字签名。当 B 要向 A 发送消息并证明消息的来源和完整性时,B 可以使用自己的私钥对消息进行签名。A 收到消息和签名后,使用 B 的公钥对签名进行验证。如果验证通过,则说明消息确实是由 B 发送的,并且在传输过程中没有被篡改。

证书与公钥、私钥的关系

  • 绑定身份和公钥:证书的主要作用是将公钥与实体的身份信息绑定在一起。证书中包含了实体的身份信息(如名称、组织、地址等)和公钥,并且由 CA 使用自己的私钥进行签名。这样,其他方可以通过验证 CA 的签名来确认证书的真实性,从而信任证书中所包含的公钥的所有者身份。
  • 公钥分发:证书解决了公钥分发过程中的信任问题。在没有证书的情况下,当一方获取到另一方的公钥时,无法确定该公钥是否确实属于声称的所有者。而通过使用证书,公钥的分发可以通过 CA 的信任链来进行。只要信任 CA,就可以信任由该 CA 颁发的证书中的公钥。
  • 证书依赖私钥签名:CA 在颁发证书时,使用自己的私钥对证书内容进行签名。这个签名可以被其他方使用 CA 的公钥进行验证,以确保证书的完整性和真实性。同时,证书的所有者在使用公钥进行通信时,也可以使用自己的私钥进行数字签名,以证明自己的身份。

举例说明

假设企业 A 要与企业 B 进行安全通信:

  1. 密钥生成:企业 A 和企业 B 各自使用密码学算法生成自己的公钥 - 私钥对。
  2. 证书申请:企业 A 和企业 B 分别向受信任的 CA 申请数字证书。他们将自己的身份信息和公钥提交给 CA。
  3. 证书颁发:CA 对企业 A 和企业 B 的身份进行验证,验证通过后,使用自己的私钥对企业 A 和企业 B 的身份信息和公钥进行签名,生成数字证书并颁发给他们。
  4. 安全通信:当企业 A 要向企业 B 发送保密信息时,企业 A 从企业 B 的证书中获取企业 B 的公钥,使用该公钥对信息进行加密后发送给企业 B。企业 B 收到加密信息后,使用自己的私钥进行解密。同时,企业 B 可以使用自己的私钥对回复信息进行签名,企业 A 使用企业 B 证书中的公钥对签名进行验证,确保信息的来源和完整性。

二、在 CentOS 7.5 上搭建 CA 服务详细步骤

1. 安装 OpenSSL

A机器
B机器

OpenSSL 是一个开源的 SSL/TLS 协议实现,提供了创建和管理证书的工具。在 CentOS 7.5 上,我们可以使用 yum 包管理器来安装 OpenSSL。

# 执行以下命令安装 OpenSSL 及其开发库
yum install -y openssl openssl-devel

2. 创建 CA 工作目录

A机器

为了更好地管理 CA 相关的文件,我们需要创建一个专门的工作目录,并在其中创建一些子目录用于存放不同类型的文件。

# 创建 CA 主目录
mkdir -p /etc/pki/CA
# 进入 CA 主目录
cd /etc/pki/CA

# 创建子目录
mkdir -p certs crl newcerts private

# 设置 private 目录的权限,确保私钥文件的安全性
chmod 700 private

# 创建证书数据库文件,用于记录已颁发证书的信息
touch index.txt

# 创建证书序列号文件,并初始化为 1000
echo 1000 > serial

3. 配置 OpenSSL

A机器

我们需要编辑 OpenSSL 的配置文件 /etc/pki/tls/openssl.cnf,根据实际需求修改其中的一些参数。

# 打开 OpenSSL 配置文件进行编辑
vi /etc/pki/tls/openssl.cnf

在文件中找到并修改以下部分:

[ CA_default ]
# CA 工作目录
dir             = /etc/pki/CA           # Where everything is kept
# 已颁发证书存放目录
certs           = $dir/certs            # Where the issued certs are kept
# 证书吊销列表存放目录
crl_dir         = $dir/crl              # Where the issued crl are kept
# 证书数据库文件
database        = $dir/index.txt        # database index file.
# 是否允许创建具有相同主题的多个证书,这里设置为 no
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
# 新证书存放目录
new_certs_dir   = $dir/newcerts         # default place for new certs.

# CA 证书文件
certificate     = $dir/cacert.pem       # The CA certificate
# 证书序列号文件
serial          = $dir/serial           # The current serial number
# 证书吊销列表编号文件
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
# 证书吊销列表文件
crl             = $dir/crl.pem          # The current CRL
# CA 私钥文件
private_key     = $dir/private/cakey.pem# The private key
# 随机数文件
RANDFILE        = $dir/private/.rand    # private random number file

# 证书扩展选项
x509_extensions = usr_cert              # The extentions to add to the cert

# 注释掉以下两行以使用传统格式
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt        = ca_default            # Subject Name options
cert_opt        = ca_default            # Certificate field options

# 扩展复制选项,使用时需谨慎
copy_extensions = copy

# 要添加到证书吊销列表的扩展,Netscape 通信器不支持 V2 CRL,因此默认注释掉以生成 V1 CRL
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions        = crl_ext

# 证书默认有效期(天)
default_days    = 365                   # how long to certify for
# 证书吊销列表更新间隔(天)
default_crl_days= 30                    # how long before next CRL
# 默认使用的消息摘要算法
default_md      = sha256                # use public key default MD
# 是否保留传递的 DN 顺序
preserve        = no                    # keep passed DN ordering

# CA 策略
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy          = policy_match

# CA 策略匹配规则
[ policy_match ]
# 国家名称必须匹配
countryName             = match
# 省份名称必须匹配
stateOrProvinceName     = match
# 组织名称必须匹配
organizationName        = match
# 组织单位名称可选
organizationalUnitName  = optional
# 通用名称必须提供
commonName              = supplied
# 电子邮件地址可选
emailAddress            = optional

# 任意策略,所有字段均可选
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

4. 创建 CA 根证书

4.1 生成 CA 私钥

A机器

使用 openssl genrsa 命令生成 CA 的私钥,并设置合适的权限。

# 生成 2048 位的 CA 私钥
openssl genrsa -out /etc/pki/CA/private/cakey.pem 2048

# 设置私钥文件的权限为 400,只有所有者可以读取
chmod 400 /etc/pki/CA/private/cakey.pem

4.2 生成 CA 自签名证书

A机器

使用生成的私钥创建 CA 自签名证书。

# 生成 CA 自签名证书,有效期为 3650 天
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3650

在执行上述命令时,会提示输入一些证书信息,以下是各字段的含义及示例填写:

  • Country Name (2 letter code) [XX]:国家代码,如 CN 表示中国。
  • State or Province Name (full name) []:省份名称,如 Guangdong
  • Locality Name (eg, city) [Default City]:城市名称,如 Shenzhen
  • Organization Name (eg, company) [Default Company Ltd]:组织名称,如 Example Company
  • Organizational Unit Name (eg, section) []:组织单位名称,可根据实际情况填写,如 IT Department
  • Common Name (eg, your name or your server's hostname) []:通用名称,通常填写 CA 的名称,如 Example CA
  • Email Address []:电子邮件地址,可填写管理员的邮箱。

查看证书的基本信息

使用 openssl x509 命令并结合 -noout 和 -subject、-issuer、-dates 等选项来查看证书的基本信息,例如主题、颁发者、有效期等。
查看证书主题信息

openssl x509 -in cacert.pem -noout -subject

该命令会输出证书的主题信息,主题信息包含了证书所有者的相关标识,比如组织名称、通用名称等。

5. 为客户端生成证书

B机器

5.1 生成客户端私钥

假设客户端名称为 client,我们需要为其生成私钥。

# 创建客户端工作目录
mkdir -p /tmp/client
# 进入客户端工作目录
cd /tmp/client

# 生成 2048 位的客户端私钥
openssl genrsa -out client.key 2048

5.2 生成证书签名请求(CSR)

B机器

使用客户端私钥生成证书签名请求(CSR)。

# 生成客户端证书签名请求
openssl req -new -key client.key -out client.csr
# 查看证书信息
openssl req -in client.csr  -noout -subject

在执行上述命令时,同样会提示输入一些证书信息,填写时要与 CA 的策略匹配。各字段含义与生成 CA 证书时类似。

5.3 B机器配置免密登录A机器

B机器

使用 SSH 密钥认证

为了避免每次传输文件都输入密码,可以使用 SSH 密钥认证。以下是设置步骤:

生成 SSH 密钥对

在本地机器上,使用以下命令生成 SSH 密钥对:

ssh-keygen -t rsa

按照提示一路回车,密钥对会生成在 ~/.ssh 目录下,默认的私钥文件是 id_rsa,公钥文件是 id_rsa.pub

将公钥复制到远程机器

使用以下命令将公钥复制到远程机器:

ssh-copy-id user@192.168.1.100(A机器IP)

输入远程机器用户的密码后,公钥会被复制到远程机器的 ~/.ssh/authorized_keys 文件中。之后再使用 scpsftp 进行文件传输时,就不需要输入密码了。

5.4 B机器将证书申请传到A机器

B机器

scp client.csr  root@192.168.40.128:/root

6. CA 签署客户端证书

将客户端的 CSR 发送到 CA 服务器,使用 CA 进行签署。

# 使用 CA 签署客户端证书,有效期为 365 天
openssl ca -in /tmp/client/client.csr -out /tmp/client/client.crt -days 365

在签署过程中,会提示确认一些信息,按照提示输入 y 确认即可。

7. 验证证书

可以使用以下命令验证客户端证书。

# 验证客户端证书
openssl verify -CAfile /etc/pki/CA/cacert.pem /tmp/client/client.crt

如果输出 /tmp/client/client.crt: OK,则表示证书验证成功。