如何在根 CA 下生成服务器和客户端证书

How to generate both server and client certificates under root CA

所以,我一直在尝试在 python 客户端和 python 服务器之间建立 SSL 连接,其中两者都有单独的证书来相互验证,并且两个证书都已签名由一个 CA(也恰好是根 CA)。这应该使它们对彼此有效,对吗?

到目前为止,我的方法是创建一个 bash 脚本来完成这一切:

  1. 它为根 CA 生成私钥
  2. 它使用根 CA 私钥生成根 CA 证书
  3. 它为服务器生成私钥
  4. 它为服务器生成 CSR
  5. 它使用服务器 CSR 和根 CA 证书生成服务器证书
  6. 为客户端生成私钥
  7. 它为客户生成 CSR
  8. 它使用客户端 CSR 和根 CA 证书生成客户端证书
#!/bin/bash

BOLD=$(tput bold)
CLEAR=$(tput sgr0)

echo -e "${BOLD}Generating RSA AES-256 Private Key for Root Certificate Authority${CLEAR}"
openssl genrsa -aes256 -out Root.CA.example.llc.key 4096

echo -e "${BOLD}Generating Certificate for Root Certificate Authority${CLEAR}"
openssl req -x509 -new -nodes -key Root.CA.example.llc.key -sha256 -days 1825 -out Root.CA.example.llc.pem

echo -e "${BOLD}Generating RSA Private Key for Server Certificate${CLEAR}"
openssl genrsa -out server/example.llc.server.key 4096

echo -e "${BOLD}Generating Certificate Signing Request for Server Certificate${CLEAR}"
openssl req -new -key server/example.llc.server.key -out server/example.llc.server.csr

echo -e "${BOLD}Generating Certificate for Server Certificate${CLEAR}"
openssl x509 -req -in server/example.llc.server.csr -CA Root.CA.example.llc.pem -CAkey Root.CA.example.llc.key -CAcreateserial -out server/example.llc.server.crt -days 1825 -sha256 -extfile server/example.llc.server.ext

echo -e "${BOLD}Generating RSA Private Key for Client Certificate${CLEAR}"
openssl genrsa -out client/example.llc.client.key 4096

echo -e "${BOLD}Generating Certificate Signing Request for Client Certificate${CLEAR}"
openssl req -new -key client/example.llc.client.key -out client/example.llc.client.csr

echo -e "${BOLD}Generating Certificate for Client Certificate${CLEAR}"
openssl x509 -req -days 1825 -in client/example.llc.client.csr -CA Root.CA.example.llc.pem -CAkey Root.CA.example.llc.key -set_serial 01 -out client/example.llc.client.crt

echo "Done!"

服务器加载这些凭据:

cntx = SSL.Context(...)
# ...
cntx.use_privatekey_file('example.llc.server.key')
cntx.use_certificate_file('example.llc.server.cert')
cntx.load_verify_locations('../Root.CA.example.llc.pem')

客户端加载这些凭据:

cntx = SSL.Context(...)
# ...
cntx.use_privatekey_file('example.llc.client.key')
cntx.use_certificate_file('example.llc.client.cert')
cntx.load_verify_locations('../Root.CA.example.llc.pem')

服务器如火箭般发射

server = SSL.Connection(cntx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
server.bind(('localhost', 44000))
server.listen(1)
server.setblocking(1)
cli, addr = server.accept()

并且客户端尝试连接

SSL.Connection(cntx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
sock.connect(('localhost', 44000))

然后我被这种疯狂击中了:

OpenSSL.SSL.Error: [('SSL routines', 'ssl3_read_bytes', 'tlsv1 alert unknown ca')]

在这一点上,我不确定客户端和服务器证书是否应该由根 CA 签名,客户端证书是否应该由服务器证书签名,或者我是否对这一切感到疯狂证书信任链 SSL/TLS 魔法巫师巫毒疯狂。请帮忙。

这就是她写的全部!

Steve E. 指出证书需要验证,因此发现罪魁祸首是自签名客户端证书。

openssl verify -verbose -CAfile Root.CA.example.llc.pem server/example.llc.server.crt
openssl verify -verbose -CAfile Root.CA.example.llc.pem client/example.llc.client.crt

这是新的 autogen 代码:

#!/bin/bash

BOLD=$(tput bold)
CLEAR=$(tput sgr0)

echo -e "${BOLD}Generating RSA AES-256 Private Key for Root Certificate Authority${CLEAR}"
openssl genrsa -aes256 -out Root.CA.example.llc.key 4096

echo -e "${BOLD}Generating Certificate for Root Certificate Authority${CLEAR}"
openssl req -x509 -new -nodes -key Root.CA.example.llc.key -sha256 -days 1825 -out Root.CA.example.llc.pem

echo -e "${BOLD}Generating RSA Private Key for Server Certificate${CLEAR}"
openssl genrsa -out server/example.llc.server.key 4096

echo -e "${BOLD}Generating Certificate Signing Request for Server Certificate${CLEAR}"
openssl req -new -key server/example.llc.server.key -out server/example.llc.server.csr

echo -e "${BOLD}Generating Certificate for Server Certificate${CLEAR}"
openssl x509 -req -in server/example.llc.server.csr -CA Root.CA.example.llc.pem -CAkey Root.CA.example.llc.key -CAcreateserial -out server/example.llc.server.crt -days 1825 -sha256 -extfile server/example.llc.server.ext

echo -e "${BOLD}Generating RSA Private Key for Client Certificate${CLEAR}"
openssl genrsa -out client/example.llc.client.key 4096

echo -e "${BOLD}Generating Certificate Signing Request for Client Certificate${CLEAR}"
openssl req -new -key client/example.llc.client.key -out client/example.llc.client.csr

echo -e "${BOLD}Generating Certificate for Client Certificate${CLEAR}"
openssl x509 -req -in client/example.llc.client.csr -CA Root.CA.example.llc.pem -CAkey Root.CA.example.llc.key -CAcreateserial -out client/example.llc.client.crt -days 1825 -sha256

echo "Done!"

祝所有尝试为 client/server 系统创建具有双面身份验证的自签名根 CA 的人好运!