Hi I'm using the python library Websockets . In developement everything was working, but on the server it crashes because it needs to use WSS. The link above gives an example how to do this:
#!/usr/bin/env python
# WSS (WS over TLS) server example, with a self-signed certificate
import asyncio
import pathlib
import ssl
import websockets
async def hello(websocket, path):
name = await websocket.recv()
print(f"< {name}")
greeting = f"Hello {name}!"
await websocket.send(greeting)
print(f"> {greeting}")
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
localhost_pem = pathlib.Path(__file__).with_name("localhost.pem")
ssl_context.load_cert_chain(localhost_pem)
start_server = websockets.serve(
hello, "localhost", 8765, ssl=ssl_context
)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
This code is straightforward enough, but I am totally lost on how to generate the file it wants (both for server and client). I've researched "creating a pem file" to no avail and have recieved all sorts of ssl errors. Can someone please explain how to create the pem file for this application? Thanks
EDIT: Per the answer I used
sudo openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
this created two files.
My server now successfully listens by doing:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
path_cert = pathlib.Path(__file__).with_name("cert.pem")
path_key = pathlib.Path(__file__).with_name("key.pem")
ssl_context.load_cert_chain(path_cert, keyfile=path_key)
print("Listening for connection...")
start_server = websockets.serve(handler, HOSTNAME, PORT, ssl=ssl_context)
The only part left I'm having issues is getting the client to connect, I try:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
path_cert = pathlib.Path(__file__).with_name("cert.pem")
ssl_context.load_cert_chain(path_cert)
async with websockets.connect(uri, ssl=ssl_context) as websocket:
But I get the error: ssl.SSLError: [SSL] PEM lib (_ssl.c:3854)
I also tried:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
path_cert = pathlib.Path(__file__).with_name("cert.pem")
path_key = pathlib.Path(__file__).with_name("key.pem")
ssl_context.load_cert_chain(path_cert, keyfile=path_key)
async with websockets.connect(uri, ssl=ssl_context) as websocket:
and get the error ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1076)
EDIT2: Per answer I tried this for the client:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.load_verify_locations()
async with websockets.connect(uri, ssl=ssl_context) as websocket:
This generates a new error: TypeError: cafile, capath and cadata cannot be all omitted
Trying the second suggestion:
ssl_context = ssl.create_default_context()
ssl_context.load_verify_locations(certifi.where())
async with websockets.connect(uri, ssl=ssl_context) as websocket:
Generates error: ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1076)
EDIT3: The final working client:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
path_cert = pathlib.Path(__file__).with_name("cert.pem")
ssl_context.load_verify_locations(path_cert)
async with websockets.connect(uri, ssl=ssl_context) as websocket:
PEM file contains somethings about public key or|and private key or certificates, and it has base64-encoded bit of data. PEM means Privacy-Enhanced Mail for mail security standard. It includes header and footer lines of the form
How to create a self-signed PEM file
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
How to create a PEM file from existing certificate files that form a chain (optional) Remove the password from the Private Key by following the steps listed below:
openssl rsa -in server.key -out nopassword.key
How to create a PEM file with the help of an automated script:
Download NetIQ Cool Tool OpenSSL-Toolkit.
Select Create Certificates | PEM with key and entire trust chain
Provide the full path to the directory containing the certificate files.
Provide the filenames of the following: private key public key (server crt) (conditional) password for private key (conditional) any intermediate certificate chain file(s)
You will have something like this:
-----BEGIN RSA PRIVATE KEY-----
(Private Key: domain_name.key contents)
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
(Primary SSL certificate: domain_name.crt contents)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Intermediate certificate: certChainCA.crt contents)
-----END CERTIFICATE----
You can decode it:
openssl x509 -in cert.pem -text -noout
You will have something like this:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0 (0x0)
Signature Algorithm: ecdsa-with-SHA256
Issuer: C = BE, O = GnuTLS, OU = GnuTLS certificate authority, ST = Leuven, CN = GnuTLS certificate authority
Validity
Not Before: May 23 20:38:21 2011 GMT
Not After : Dec 22 07:41:51 2012 GMT
Subject: C = BE, O = GnuTLS, OU = GnuTLS certificate authority, ST = Leuven, CN = GnuTLS certificate authority
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:52:d8:8d:23:8a:e3:67:d7:86:36:b1:20:0b:09:
7d:c8:c9:ba:a2:20:95:2f:c5:4a:63:fa:83:5f:ce:
78:2f:8f:f3:62:ca:fd:b7:f7:80:56:9d:6e:17:b9:
0e:11:4c:48:b2:c0:af:3b:59:17:16:30:68:09:07:
99:17:fe:dd:a7
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Subject Key Identifier:
F0:B4:81:FE:98:12:BF:B5:28:B9:64:40:03:CB:CC:1F:66:4E:28:03
Signature Algorithm: ecdsa-with-SHA256
30:45:02:20:31:ae:c0:3d:4a:3f:21:be:85:17:fc:f0:c7:b2:
31:07:2a:38:56:43:d1:36:d5:95:e1:7e:52:c0:06:43:87:a7:
02:21:00:97:8c:0e:b8:3c:0a:41:af:ae:a5:cf:06:7e:d5:c4:
d8:2f:ff:e2:62:80:34:10:ba:22:dd:35:81:46:93:22:9a
For client section you wrote:
ssl_context.load_cert_chain(path_cert, keyfile=path_key)
Replace it:
import json
import asyncio
import websockets
import ssl
import certifi
ssl_context = ssl.create_default_context()
ssl_context.load_verify_locations(certifi.where())
query = {
"jsonrpc": "2.0",
"method": "queryHeadsets",
"params": {},
"id": 1
}
json = json.dumps(query)
async def query(json):
async with websockets.connect("wss://yourserver.com:54321", ssl=ssl_context) as ws:
await ws.send(json)
response = await ws.recv()
print(response)
asyncio.get_event_loop().run_until_complete(query(json))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.