在Linux系统中,使用OpenSSL实现双向认证(也称为客户端证书认证)涉及以下几个步骤:
首先,你需要创建一个证书颁发机构(CA),并生成CA证书和私钥。
# 创建CA目录
mkdir -p ca/newcerts
# 创建CA配置文件
cat <<EOF > ca/openssl.cnf
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /etc/ssl/ssl-ca
certs = \$dir/certs
crl_dir = \$dir/crl
new_certs_dir = \$dir/newcerts
database = \$dir/index.txt
serial = \$dir/serial
RANDFILE = \$dir/private/.rand
private_key = \$dir/private/ca.key.pem
certificate = \$dir/cacert.pem
crlnumber = \$dir/crlnumber
crl = \$dir/crl.pem
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 3650
preserve = no
policy = policy_strict
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOF
# 创建CA目录结构
mkdir -p ca/newcerts ca/private ca/crl ca/certs
# 生成CA私钥
openssl genpkey -algorithm RSA -out ca/private/ca.key.pem 4096
# 生成CA证书
openssl req -config ca/openssl.cnf -key ca/private/ca.key.pem -new -x509 -days 3650 -sha256 -extensions v3_ca -out ca/cacert.pem
# 初始化CA数据库
echo 1000 > ca/serial
touch ca/index.txt
openssl crl -config ca/openssl.cnf -in ca/crl.pem -out ca/crl_new.pem
mv ca/crl_new.pem ca/crl.pem
接下来,生成服务器证书和私钥。
# 创建服务器目录结构
mkdir -p server/newcerts server/private server/certs
# 创建服务器配置文件
cat <<EOF > server/openssl.cnf
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = server.example.com
[ v3_req ]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = server.example.com
DNS.2 = www.example.com
[ v3_server ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:false
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
EOF
# 创建服务器私钥
openssl genpkey -algorithm RSA -out server/private/server.key.pem 4096
# 生成服务器证书签名请求(CSR)
openssl req -config server/openssl.cnf -key server/private/server.key.pem -new -out server/server.csr
# 使用CA证书和私钥签署服务器证书
openssl x509 -req -in server/server.csr -CA ca/cacert.pem -CAkey ca/private/ca.key.pem -CAcreateserial -out server/server.crt -days 3650 -sha256 -extfile server/openssl.cnf -extensions v3_server
生成客户端证书和私钥。
# 创建客户端目录结构
mkdir -p client/newcerts client/private client/certs
# 创建客户端配置文件
cat <<EOF > client/openssl.cnf
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = client.example.com
[ v3_req ]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = client.example.com
DNS.2 = www.client.example.com
[ v3_client ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:false
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
EOF
# 创建客户端私钥
openssl genpkey -algorithm RSA -out client/private/client.key.pem 4096
# 生成客户端证书签名请求(CSR)
openssl req -config client/openssl.cnf -key client/private/client.key.pem -new -out client/client.csr
# 使用CA证书和私钥签署客户端证书
openssl x509 -req -in client/client.csr -CA ca/cacert.pem -CAkey ca/private/ca.key.pem -CAcreateserial -out client/client.crt -days 3650 -sha256 -extfile client/openssl.cnf -extensions v3_client
编辑服务器配置文件(例如/etc/ssl/ssl-ca/server/openssl.cnf),添加以下内容:
[ server ]
listen = 443
cert = /etc/ssl/ssl-ca/server/server.crt
key = /etc/ssl/ssl-ca/server/server.key.pem
CAfile = /etc/ssl/ssl-ca/ca/cacert.pem
verify = 2
require_client_cert = yes
编辑客户端配置文件(例如/etc/ssl/ssl-ca/client/openssl.cnf),添加以下内容:
[ client ]
default_ca = CA_default
cert = /etc/ssl/ssl-ca/client/client.crt
key = /etc/ssl/ssl-ca/client/client.key.pem
verify_depth = 4
verify_return_error = yes
启动服务器并验证客户端证书。
openssl s_server -cert /etc/ssl/ssl-ca/server/server.crt -key /etc/ssl/ssl-ca/server/server.key.pem -CAfile /etc/ssl/ssl-ca/ca/cacert.pem -Verify 2 -accept 443
openssl s_client -connect server.example.com:443 -cert /etc/ssl/ssl-ca/client/client.crt -key /etc/ssl/ssl-ca/client/client.key.pem -CAfile /etc/ssl/ssl-ca/ca/cacert.pem
通过以上步骤,你可以在Linux系统中使用OpenSSL实现双向认证。