首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python未知CA错误

Python未知CA错误
EN

Stack Overflow用户
提问于 2018-06-19 04:34:43
回答 1查看 3.3K关注 0票数 1

我目前正在阅读Python网络编程的基础,并看到了以下示例,演示如何使用Python的ssl模块:

清单6-3:在Python3.4或更高版本中为客户端和服务器保护一个套接字

代码语言:javascript
复制
#!/usr/bin/env python3
# Foundations of Python Network Programming, Third Edition
# https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter06/safe_tls.py
# Simple TLS client and server using safe configuration defaults

import argparse, socket, ssl

def client(host, port, cafile=None):
    purpose = ssl.Purpose.SERVER_AUTH
    context = ssl.create_default_context(purpose, cafile=cafile)

    raw_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    raw_sock.connect((host, port))
    print('Connected to host {!r} and port {}'.format(host, port))
    ssl_sock = context.wrap_socket(raw_sock, server_hostname=host)

    while True:
        data = ssl_sock.recv(1024)
        if not data:
            break
        print(repr(data))

def server(host, port, certfile, cafile=None):
    purpose = ssl.Purpose.CLIENT_AUTH
    context = ssl.create_default_context(purpose, cafile=cafile)
    context.load_cert_chain(certfile)

    listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    listener.bind((host, port))
    listener.listen(1)
    print('Listening at interface {!r} and port {}'.format(host, port))
    raw_sock, address = listener.accept()
    print('Connection from host {!r} and port {}'.format(*address))
    ssl_sock = context.wrap_socket(raw_sock, server_side=True)

    ssl_sock.sendall('Simple is better than complex.'.encode('ascii'))
    ssl_sock.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Safe TLS client and server')
    parser.add_argument('host', help='hostname or IP address')
    parser.add_argument('port', type=int, help='TCP port number')
    parser.add_argument('-a', metavar='cafile', default=None,
                        help='authority: path to CA certificate PEM file')
    parser.add_argument('-s', metavar='certfile', default=None,
                        help='run as server: path to server PEM file')
    args = parser.parse_args()
    if args.s:
        server(args.host, args.port, args.s, args.a)
    else:
        client(args.host, args.port, args.a)

书中说要下载以下两个文件,即主机名“localhost”的自签名CA和第二个CA (由自签名CA签名):

因此,代码应该按以下方式运行:

  • 服务器 python safe_tls.py -s localhost.pem '‘1060
  • 客户端 python safe_tls.py -a ca.crt localhost 1060

但是,每当我一起运行服务器和客户端时,都会得到以下错误:

  • 服务器 从主机'127.0.0.1‘和端口35148回溯(最近一次调用)侦听接口'’和端口1060连接:文件"safe_tls.py",第50行,在服务器(args.host,args.port,args.s,args.a)文件"safe_tls.py",第35行,在服务器ssl_sock =context.wrap_socket= context.wrap_socket(raw_sock,server_side=True) File "/usr/lib/python3.6/ssl.py",第407行,在wrap_socket _context=self中,_session=session)文件"/usr/lib/python3.6/ssl.py",第814行,__init__ self.do_handshake() File "/usr/lib/python3.6/ssl.py",第1068行,do_handshake self._sslobj.do_handshake() File "/usr/lib/python3.6/ssl.py",第689行,在do_handshake self._sslobj.do_handshake() ssl.SSLError: SSL: TLSV1_ALERT_UNKNOWN_CA tlsv1警报未知ca (_ssl.c:833)中
  • 客户端 连接到主机'localhost‘和端口1060回溯(最近一次调用):文件"safe_tls.py",第52行,客户端(args.host,args.port,args.a)文件"safe_tls.py",第15行,客户端ssl_sock = context.wrap_socket(raw_sock,server_hostname=host)文件"/usr/lib/python3.6/ssl.py",第407行,wrap_socket _context=self,_session=session)文件"/usr/lib/python3.6/ssl.py",第814行,在__init__ self.do_handshake() File "/usr/lib/python3.6/ssl.py“中,第1068行,在do_handshake self._sslobj.do_handshake() File "/usr/lib/python3.6/ssl.py”中,第689行,在do_handshake self._sslobj.do_handshake() ssl.SSLError: SSL: CERTIFICATE_VERIFY_FAILED证书验证失败(_ssl.c:833)中

我已经尝试为主机名"localhost“生成自己的自签名CA和辅助CA (由自签名CA签名),但在运行客户机和服务器时仍然会出现相同的错误。

有人能告诉我我做错了什么吗?

谢谢。

P.S. I在Ubuntu18.04LTS上运行Python3.6.5,以防万一.

更新

我能够让上面的代码在没有二级证书的情况下工作,但是可以使用我生成的单个自签名证书,如下所示:

代码语言:javascript
复制
$ openssl req -x509 -nodes -newkey rsa:4096 -keyout localhost.key -new -out localhost.crt
$ cat localhost.crt localhost.key > localhost.pem

然后,我按照上面描述的方式运行了safe_tls.py程序,除了使用localhost.crt而不是ca.crt

尽管如此,我仍然希望能够与另一个CA签署,然后使用次要CA,正如我最初试图。任何帮助找出如何做这将是非常感谢!

EN

回答 1

Stack Overflow用户

发布于 2018-06-19 06:16:51

好的,所以我最终找到了我自己问题的答案,所以我会在这里发布。

我不知道在Python编程基础的公共回购中提供的ca.crtlocalhost.pem文件有什么问题;但是,我成功地生成并签署了自己的CA,使它按照我最初的要求工作。

下面是我必须输入的命令:

代码语言:javascript
复制
$ # I don't know what these files are, but OpenSSL complains if they do not exist...
$ mkdir demoCA
$ touch demoCA/index.txt demoCA/index.txt.attr
$ echo '01' > demoCA/serial
$ # Create a self-signed certificate and private key.
$ openssl req -x509 -nodes -newkey rsa:4096 -keyout ca.key -new -out ca.crt
$ # Create a certificate signing request for server, "localhost", and a private key.
$ openssl req -nodes -newkey rsa:4096 -keyout localhost.key -new -out localhost.csr
$ # Sign the certificate request.
$ openssl ca -keyfile ca.key -cert ca.crt -in localhost.csr -outdir . -out localhost.crt
$ cat localhost.crt localhost.key > localhost.pem

注:

对于上面执行的每个openssl req ...命令,我必须在命令行中填写一些信息(因为我没有创建配置文件)。除主机名和电子邮件外,所有信息必须在两个证书之间相同,否则最后一个命令(我们在证书请求中签名)将失败。

现在可以成功地运行服务器和客户端,如最初所示:

  • 服务器 python safe_tls.py -s localhost.pem '‘1060
  • 客户端 python safe_tls.py -a ca.crt localhost 1060
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50920710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档