如何在根 CA 下生成服务器和客户端证书
How to generate both server and client certificates under root CA
所以,我一直在尝试在 python 客户端和 python 服务器之间建立 SSL 连接,其中两者都有单独的证书来相互验证,并且两个证书都已签名由一个 CA(也恰好是根 CA)。这应该使它们对彼此有效,对吗?
到目前为止,我的方法是创建一个 bash 脚本来完成这一切:
- 它为根 CA 生成私钥
- 它使用根 CA 私钥生成根 CA 证书
- 它为服务器生成私钥
- 它为服务器生成 CSR
- 它使用服务器 CSR 和根 CA 证书生成服务器证书
- 为客户端生成私钥
- 它为客户生成 CSR
- 它使用客户端 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 的人好运!
所以,我一直在尝试在 python 客户端和 python 服务器之间建立 SSL 连接,其中两者都有单独的证书来相互验证,并且两个证书都已签名由一个 CA(也恰好是根 CA)。这应该使它们对彼此有效,对吗?
到目前为止,我的方法是创建一个 bash 脚本来完成这一切:
- 它为根 CA 生成私钥
- 它使用根 CA 私钥生成根 CA 证书
- 它为服务器生成私钥
- 它为服务器生成 CSR
- 它使用服务器 CSR 和根 CA 证书生成服务器证书
- 为客户端生成私钥
- 它为客户生成 CSR
- 它使用客户端 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 的人好运!