I'm following a Python twisted tutorial in which an echo server is being set up in order to talk to a client over a ssl transport layer. The end goal is to obtain an encrypted connection towards our end product. From GUI to a remote embedded client.
The application can be found here: Twisted matrix SSL example
I've created a set of keys like this:
$ openssl req -x509 -newkey rsa:4096 -keyout keys/server.key -out keys/server.crt -sha256
This works except for the fact that the server in this case keeps on asking for the PEM passphrase at every connection from the client.
Enter PEM pass phrase:
My question: How can I make this setup work without inserting my password every time?
I'm afraid to make some hacker friendly mistake in this matter so I would also appreciate any additional safety tips.
TY
I've found a solution ( or workaround ) for this particular problem. I just route the key back into openssl to create a new one.
The first time it would not let me create a key without a pass phrase. This time it only needs a passphrase for accessing the first key. I can't help thinking this is just a trick.
openssl rsa -in server.key -out server_bis.key
Now it works without asking for password every time the client connects.
Zero points for security :-)
Related
I am very new to python and cannot seem to figure out how to accomplish this task. I want to connect to a website and extract the certificate information such as issuer and expiration dates.
I have looked all over, tried all kinds of steps but because I am new I am getting lost in the socket, wrapper etc.
To make matters worse, I am in a proxy environment and it seems to really complicate things.
Does anyone know how I could connect and extract the information while behind the proxy?
As explained in this Answer:
You can still the server certificate with the
ssl.get_server_certificate() function, but it returns it in PEM
format.
import ssl
print ssl.get_server_certificate(('server.test.com', 443))
From here, I would use M2Crypto or OpenSSL to read the cert and get values:
# M2Crypto
cert = ssl.get_server_certificate(('www.google.com', 443))
x509 = M2Crypto.X509.load_cert_string(cert)
x509.get_subject().as_text()
# 'C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com'
Python SSL lib don't deal with proxies.
import OpenSSL
key = ...
signature = ...
data = ...
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, key)
OpenSSL.crypto.verify(x509, signature, data, 'sha1')
So far, I am able to do all of this without any problems. However, it doesn't feel like this is enough security, since the key itself is given to me via an URL (that I am supposed to trust*), and the method to build the signature is publicly available.
So, say the key is said to be verified by "VeriSign Class 3 Code Signing 2010 CA", can anyone tell me how I can go about checking that this is a valid claim?
I'm guessing I need to have the VeriSign certificate locally on my machine. Assuming that I do, where do I go from there?
Thanks!
*the URL is given to me as a parameter in a JSON request. Sure, the URL will be HTTPS and I can check the domain name and all that. But it seems like I should be doing checks on the certificate itself
You are right that you should check the certificate itself. And yes, you need the VeriSign root certificate(s) (and any other intermediate certificates to have the complete chain of trust) which signed the certificate to be checked.
Current Symantec (VeriSign) root certificates can be found here in zipfile.
Download and unzip the zip file and find all certificates you wish to trust and put them together (in pem format) into one certificate bundle file.
Now you need to do the actual verification. Unfortunately, the OpenSSL call you need is X509_verify_certificate. I looked at the source for both pyopenssl and M2Crypto and neither expose that call, so there's no direct Python code you can call to verify the certificate with either of those packages.
However, since you are using pyopenssl you obviously have the openssl library available. Thus you probably already have or can easily install the openssl command-line tool set. If so, you can call the openssl verify command through a pipe by doing something like this:
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, key)
# the command like likes pem format
cert_pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
# the bundle that you created from the zip extraction
certificate_bundle = 'verisign-root-bundle.pem'
# Pipe the cert to the openssl verify command and check the return code
# a return code of 0 is successful verify
import subprocess
p = subprocess.Popen(['openssl', 'verify', '-CAfile', certificate_bundle],
stdin=subprocess.PIPE)
p.communicate(input=cert_pem)
p.wait()
if (p.returncode == 0):
print('Certificate Verified.')
else:
print('Problem with certificate')
The above pipe runs the command
openssl verify -CAfile ca.bundle certificate.pem
Finally, if you're not familiar with openssl, the command to show certificates is
openssl x509 -inform PEM -text -in certificate.pem
Hope this helps!
Maybe I only partly address your question. It seems that your largest worry is the security of the channel via which you obtain the key. You do not show any code of how you obtain that key, but you said that you retrieve it via HTTPS and now you want to verify the authenticity of this connection by certificate verification.
You can comfortably do so using the well-established third-party web client framework requests.
Quote from the docs:
Requests can verify SSL certificates for HTTPS requests, just like a
web browser. To check a host’s SSL certificate, you can use the verify
argument:
requests.get(url, verify=True)
Also:
You can pass verify the path to a CA_BUNDLE file with certificates of
trusted CAs.
The latter could look like
requests.get(url, verify='/path/to/cert.pem')
In case you really want to take control (and reduce complexity), then load the right file from http://www.symantec.com/page.jsp?id=roots and take the verify='/path/to/cert.pem' approach. I guess you need http://www.symantec.com/content/en/us/enterprise/verisign/roots/Class-3-Public-Primary-Certification-Authority-G2.pem
I've been looking into making an iOS push notification service for one of my apps lately. It has a Python 2.7 backend so I wanted to do it in Python rather than PHP (or anything else).
I've got code that sends a notification and the device receives it, however every time I run the code it asks me to manually enter a 'pass phrase' for the PEM file.
This is not ideal, as I want this to be all automated on the server, when it needs to send a notification, it should just send it. I can't find anything in the docs for Python 2.7 that allow me to automatically set the pass phrase from a variable when connecting.
If anyone knows how to do this in Python 2.7 or any other ideas I would be really grateful.
Here's a snippet of code:
certfile = 'devPEM.pem'
apns_address = ('gateway.sandbox.push.apple.com', 2195)
s = socket.socket()
sock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3, certfile=certfile)
sock.connect(apns_address)
Thanks in advance.
So the answer as BorrajaX suggested was to not set a password for the key when prompted. However this is not possible as (at least on my Mac) wants the password to be a minimum 4 characters.
The steps to fix this are:
Create the certificate in the developer portal.
Download and open the certificate locally in Keychain Access
Export the certificate’s private key as a .p12 file from Keychain Access (I named it aps_key.p12).
Run the following on the .p12 key:
openssl pkcs12 -nocerts -out aps_key.pem -in aps_key.p12
Enter a password (which we will strip in a minute).
Run the following to strip the password:
openssl rsa -in aps_key.pem -out new_aps_key.pem
Convert the .cer downloaded from the Developer Center to a .pem file:
openssl x509 -in aps.cer -inform der -out aps.pem
Merge the key and certificate .pem files with the following:
cat aps.pem new_aps_key.pem > final_aps.pem
You can now delete all other files, except for final_aps.pem.
The final_aps.pem file then works with the code above without getting prompted for a password/pass phrase.
This is a useful website where I found the code for removing the password from the .pem file: http://www.sslshopper.com/article-most-common-openssl-commands.html
Edit: If you don't need the certificate and the key in the same file, you can just ignore step 8 and use the aps.pem and new_aps_key.pem files.
I've implemented a HTTP server (CherryPy and Python) that receives an encrypted file from a client (Android). I'm using OpenSSL to decrypt the uploaded file. Currently I'm using openssl -enc -pass file:password.txt -in encryptedfile -out decryptedfile to perform to decryption on the server side. As you can see the password used by openssl is stored in a plain text file (password.txt).
Is there a more secure way to store this OpenSSL password?
Thanks.
Pass it through a higher FD, and use that FD in the command line. Note that you'll need to use the preexec_fn argument to set up the FD before the process gets run.
subprocess.Popen(['openssl', ..., 'file:/dev/fd/12', ...], ...,
preexec_fn=passtofd12(password), ...)
For the sake of privacy for a user and other reasons passwords are generally not stored by servers. Typically users choose a password which is stored as a hash of some sort on the server.
Users then authenticate with the web application by checking the stored hash against a hash supplied based on user input. Once the client is authenticated a session identifier is provided allowing use of server resource(s). During this time a user can for instance upload the file. Encryption of the file on the server should be un-necessary assuming the hosting server is secured properly and and absent of other issues.
In this case, the authentication mechanism is not made clear, neither are the threats that pose a danger, or the life cycle of that uploaded file.
It seems that a server is receiving an encrypted file, plus some type of password. Is the protection of the password being considered during the transmission phase, or as storage on the server? The HTTPS protocol can help guard against threats concerning the transmission of the file/data. As I see from your description the concern seems to be storage on the server side.
Encrypting the passwords once they have been received by the server (either individually or by using a master password) adds another layer of security, but this approach is not without fault as the passphrase either (1) needs to be stored on the server in cleartext for accessing the files (2) or needs to be entered manually by an administrator when needed as part of any processing requiring the password - note that any resources encrypted with the password become un-useable to users.
While I am not completely aware of what is going on, the most secure thing to do would be to re-work the web application and carefully think through the design and its requirements.
I'm trying to figure out how to, using m2crypto, validate the chain of trust from a public key version of a X509 certificate back to one of a set of known root CA's when the chain may be arbitrarily long. The SSL.Context module looks promising except that I'm not doing this in the context of a SSL connection and I can't see how the information passed to load_verify_locations is used.
Essentially, I'm looking for the interface that's equivalent to:
openssl verify pub_key_x509_cert
Is there something like that in m2crypto?
Thanks.
I have modified a different M2Crypto patch and with this we are able to verify a X509 Certificate against a chain of CAs, plus it allows the usage of Certificate Revocation List (CRL)s.
The heart of allowing chain verification with M2Crypto is exposing "verify_cert()" on a X509_Store_Context.
Basic flow is:
Add your CAs/CRLs to a X509_Store
Use a X509_Store_Context to verify the certificate of interest
My patch enhances CRL support as well as allowing chain verification.
https://bugzilla.osafoundation.org/show_bug.cgi?id=12954#c2
We are using this patch as part of Pulp, we have a wiki page below which shares some more info on how we are doing the verification with a chain:
https://fedorahosted.org/pulp/wiki/CertChainVerification
There is a patch that might need to be updated slightly, and it would need unit tests for me to check it in. Contributions welcome!
Another convoluted way would be to create an in-memory SSL session where you do the validation. The Twisted wrapper effectively works this way; Twisted acts as dumb network pipe without knowing anything about the data, and M2Crypto encrypts/decrypts the data in memory, doing certificate validation on the side.