Working example of Python's http.server with HTTPS? - python

I have a small open-source project: an extension of Python's http.server which allows for file uploading as well. I've received a feature request for HTTPS support, so now I am trying to test it with HTTPS, but none of the examples I've found for using HTTPS with http.server work.
So far, every example I've found suggest using ssl.wrap_socket() similar to in this one Python 3 Simple HTTPS server. The server seems to start fine but every request results in "The connection to the server was reset while the page was loading".
I've tried generating the certificates using various commands:
# Attempt 1
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out server.key
openssl rsa -passin pass:x -in server.key -out server-2.key
openssl req -new -key server-2.key -out server.csr
openssl req -new -key server.key -x509 -days 365 -out server.crt
# Attempt 2
openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
# Attempt 3
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.pem -days 365 -nodes
In each case I left the fields of the certificate blank, except for the comm name / hostname which I set to "localhost". There weren't any obvious errors, other than the connection not working.
Edit: Figured it out. My test script was still sending the requests as HTTP instead of HTTPS.

Related

Serving over HTTPS with Gunicorn/Flask: ERR_CERT_AUTHORITY_INVALID

Looking for a quick way to serve an API over HTTPS for testing purposes. The API app is created using flask and being served on port 443 using gunicorn.
gunicorn --certfile=server.crt --keyfile=server.key --bind 0.0.0.0:443 wsgi:app
When my React app (served over HTTPS) sends a POST request to one of the routes via HTTPS, the browser console is showing
POST https://1.2.3.4/foo net::ERR_CERT_AUTHORITY_INVALID
My key and certs are created using
openssl genrsa -aes128 -out server.key 2048
openssl rsa -in server.key -out server.key
openssl req -new -days 365 -key server.key -out server.csr
openssl x509 -in server.csr -out server.crt -req -signkey server.key -days 365
Is there a solution to solve ERR_CERT_AUTHORITY_INVALID raised by the browser, without using a reverse proxy like nginx/caddy? And without each user having to manually trust the self-signed cert?
Your browser/computer/device need to trust the certificate presented by gunicorn...
You should add the hostname of your PC in the certificate (Common name or Subject Alternative Name) and add the Certificate to your Trusted List of Certificates
i ran into a similar problem recently on firefox creating the cert using open ssl.
i opted for an alternative solution using mkcert
sudo apt install libnss3-tools
sudo apt install mkcert
wget https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64
sudo cp mkcert-v1.4.4-linux-amd64 /usr/local/bin/mkcert
sudo chmod +x /usr/local/bin/mkcert
mkcert -install
mkcert test.example.com '*.test.example.com' localhost 127.0.0.1 ::1
you'll want to modify /etc/hosts to include test.example.com
127.0.0.1 localhost test.example.com
don't forget to logout and log back in to update changes in hosts
if firefox still complains go to settings -> privacy/security and open View Certificates.
under the server tab, add an exception for https://test.example.com:(port #) and select Get Certificate.
then Confirm Security Exception
now fire up gunicorn using the pem format files generated by mkcert.
in my case it was something like...
gunicorn --certfile test.example.com+4.pem --keyfile test.example.com+4-key.pem
your cert should be accepted now.
each member of our team has to set this up locally. (specifically, we use an installer script to build the dev project, but the dev is responsible for installing the cert on the browser of their choosing.)
for us it was a small inconvenience for the payoff.
if this doesn't suit your needs then unfortunately yes, you might have to opt for an alternative such as caddy or nginx to reverse-proxy your requests. but you'd still have to supply a certificate using some version of the example above or via tools like certbot ect
i'd recommend a pre-config'd docker container, or a custom installer script if you're working on a team based project.

open a password protected .pem and .crt file using python

I created a private and pulic key key using command :
.....
openssl genrsa -aes256 -passout pass:password -out key.pem
4096 &&
openssl rsa -in key.pem -passin pass:password -pubout -out
pukey.pub
and then created cert file using this command:
openssl req -new -key key.pem -passin pass:password -x509 -out
keycert.pem -days 365000 -subj '/CN=localhost'
so I have protected the key.pem with a password and I want to open it in my python program, how can I specify the password to open key.pem file and keycert.pem file?
with open('../key.pem', 'rb') as f:
private_key = f.read()
with open('../keycert.pem', 'rb') as f:
certificate_chain = f.read()
when I run this I get error :
E1117 13:57:03.515461744 70812 ssl_transport_security.cc:854]
Invalid private key.
which shows it could not open the key.pem file as it is protected by a password
use this line :
with open('key.pem', 'rb') as f:
private_key=load_pem_private_key(f.read(), password="1".encode(),
backend=default_backend())
pem =private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
solved the problem , first the private key is loaded second it is converted to the bytes.

Mqtt TLS certificate verify failed : self signed certificate

Am trying to implement TLS for mqtt and has followed the tutorials from the link below
http://www.steves-internet-guide.com/mosquitto-tls/
I followed exactly how it has been instructed to generate certificates using openssl and pasted in the location of mqtt and changed the conf of mqtt and restarted the service.
But when I try to connect to mqtt using tls it shows the below error message
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1124)
And python code is
client1 = paho.Client("control1")
client1.tls_set(ca_certs="ca.crt")
client1.tls_insecure_set(True)
client1.connect("localhost", 8883)
client1.loop_forever()
where ca.crt is in the project directory.
The message you are receiving indicates that the broker's server certificate is not trusted (because it is self-signed), therefore paho is not being correctly told it is trustworthy.
It is possible your fake certificate authority's root certificate (the ca.crt file you feed to paho) is not properly signed or generated, or the certificates that Mosquitto is using are not signed correctly. Either way, you likely need to start the entire process over to be 100% certain everything was done right.
Generate the fake certificate authority's (CA) signing key
$ openssl genrsa -des3 -out ca.key 2048
Generate a certificate signing request for the fake CA
$ openssl req -new -key ca.key -out ca-cert-request.csr -sha256
Give the organization a name like "Fake Authority" and do not enter a common name (since your fake CA does not actually live on a server with a name)
Create the fake CA's root certificate
$ openssl x509 -req -in ca-cert-request.csr -signkey ca.key -out ca-root-cert.crt -days 365 -sha256
Create the server / mqtt broker's keypair
$ openssl genrsa -out server.key 2048
Create a certificate signing request using the server key to send to the fake CA for identity verification
$ openssl req -new -key server.key -out server-cert-request.csr -sha256
Give the organization a name like "Localhost MQTT Broker Inc." and the common name should be localhost or the exact domain you use to connect to the mqtt broker
Now acting as the fake CA, you receive the server's request for your signature. You have verified the server is who it says it is (an MQTT broker operating on localhost), so create a new certificate & sign it with all the power of your fake authority.
$ openssl x509 -req -in server-cert-request.csr -CA ca-root-cert.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360
Now you have everything you need. Make sure (as in Steve's tutorial) Mosquitto is loading the following in mosquitto.conf:
listener 8883
cafile certs\ca-root-cert.crt
keyfile certs\server.key
certfile certs\server.crt
Make sure paho-mqtt is loading the fake CA's root certificate.
client1.tls_set(ca_certs="ca-root-cert.crt")
This is how it knows that mosquitto's server.crt is legitimately signed by a "real and trusted authority" and is not "self-signed" and thus untrusted. Mosquitto and paho should now be able to securely connect and communicate.

The handshake operation timed out

I've mbedtls nonRTOS server device. I'm trying to communicate with PLC Client. But before the using PLC, I'm trying to use python tls client.
I've a problem with when I use below cert and key file with below method:
Generate 2048-bit RSA private key:
openssl genrsa -out key.pem 2048
Generate a Certificate Signing Request:
openssl req -new -sha256 -key key.pem -out csr.csr
Generate a self-signed x509 certificate suitable for use on web servers.
openssl req -x509 -sha256 -days 365 -key key.pem -in csr.csr -out certificate.pem
Create SSL identity file in PKCS12 as mentioned here
openssl pkcs12 -export -out client-identity.p12 -inkey key.pem -in certificate.pem
I get above code from here: Creating a .p12 file
I need to p12 file using in PLC Client. When I trying to use certificate.pem and key.pem in mbedtls-servers system and when I use the certificate.pem in python client side, I get below situation:
Server couldnt send key exchange message waiting forever.
But If I generate the key and cert file below method:
openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout key.pem
They communicate successfuly.
How can I solve the problem why the server waiting to send key exchange message when I generate key and cert file with first method

Encode PKCS7 in Google App Engine (python, passbook)

This question pertains to Passbook which is under NDA for the next few days, but this is a generic PKCS7 question.
I have a .p12 file that is exported from my keychain. I am able to separate this into 2 pems using the following commands
openssl pkcs12 -in "mycert.p12" -clcerts -nokeys -out certificate.pem
openssl pkcs12 -in "mycert.p12" -nocerts -out key.pem
The next step is to use this key and certificate to create a signed PKCS7 file. This is easy to do with openssl:
openssl smime -binary -sign \
-signer certificate.pem -inkey key.pem \
-in <datafile> -out signature \
-outform DER
The question is, what is the best way to do this in Google App Engine, assuming I have the certificate and key? Unfortunately I'm a little new to cryptography, but I've been googling around and found PyCrypto and keyczar. Is there an accepted way to do this on App Engine, or will I need to write something? Any recommendations on which package to start with?
I know that openssl is not available on AppEngine, but PyCrypto is if you use python 2.7, right? And I've seen posts of people getting keyczar to work with it. I have not been able to find a simple way of generating PKCS7-encoded data given the key and certificate, though.
Thanks in advance for any guidance.
Here's a way using M2Crypto taken from https://github.com/devartis/passbook
def passwordCallback(*args, **kwds):
return password
smime = SMIME.SMIME()
smime.load_key('key.pem', 'certificate.pem', callback=passwordCallback)
pk7 = smime.sign(SMIME.BIO.MemoryBuffer(manifest), flags=SMIME.PKCS7_DETACHED | SMIME.PKCS7_BINARY)
pem = SMIME.BIO.MemoryBuffer()
pk7.write(pem)
# convert pem to der
der = ''.join(l.strip() for l in pem.read().split('-----')[2].splitlines()).decode('base64')
open('signature', 'w').write(der)

Categories