Using Python 3, I'm trying to connect using a SSL context to a remote SMTP host, but I get the following error:
[SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:1056)
Here's the code I use:
from smtplib import SMTP
import ssl, os, certifi
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH, cafile=certifi.where())
ssl_context.options |= ssl.OP_NO_TLSv1
ssl_context.options |= ssl.OP_NO_TLSv1_1
ssl_context.load_cert_chain(os.path.join(certsdir, 'certificate.pem'), os.path.join(certsdir, 'id_rsa'))
ssl_context.load_dh_params(os.path.join(certsdir, 'dhparams.pem'))
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
smtp = SMTP(server_name)
smtp.connect((host, 25))
smtp.ehlo()
if smtp.has_extn('starttls'):
smtp.starttls(None, None, ssl_context)
smtp.ehlo()
smtp.mail(fromaddr)
smtp.rcpt(toaddr)
smtp.data(message)
smtp.quit()
Question: Is the issue on my end, or on the destination's server end? Is there something I can do to avoid this issue?
I use certifi for the list of certificates, that is based on Mozilla recommendations and is up-to-date.
Thank you for your help here.
Question: Is the issue on my end, or on the destination's server end?
The server is offering a weak DH key, the client (your script) wants a stronger key. The problem should usually be fixed at the server side. And note that your call of load_dh_params makes no sense since setting the DH key is only relevant for the server side.
Is there something I can do to avoid this issue?
Don't use DH ciphers in the first place. All modern clients support ECDHE ciphers which don't have this problem. DH is very slow anyway.
Usually the client would also choose a ECDHE cipher if offered and this error will not happen. While it might be that the TLS stack at the client is too old and prefers DH, such an old stack would usually not complain about a weak DH. It is thus more likely that the servers SSL stack is too old so that it does not offer the more modern ciphers the clients wants by default.
To make sure that no DH ciphers are offered by the client and thus ECDHE or RSA key exchange is used set the ciphers accordingly:
ssl_context.set_ciphers('DEFAULT:!DH')
Note though that RSA key exchange is considered obsolete too since it does not provide any forward secrecy. You might therefore try if the server can do without DH and without kRSA by using a cipher string of DEFAULT:!DH:!kRSA.
Related
I am currently implementing OpenSSL's TLS/SSL standards into my mail service, allowing my users to select the TLS/SSL version they want. Here is the list of versions:
["TLSv1","TLSv1_server","TLSv1_client","SSLv3","SSLv3_server","SSLv3_client","SSLv23","SSLv23_server","SSLv23_client","TLS","TLSv1_1_server","TLSv1_1_client","TLSv1_1","TLSv1_2","TLSv1_2_server","TLSv1_2_client"]
I did some Googling on what the difference of the options are, and I understand that some versions are deprecated, or shouldn't be used because of security issues, such as TLSv1. I don't understand the difference between the client vs server ones, but from my own testing, the server options return errors when trying to send a mail with it.
So my question is - of that list, what should I remove?
What you show are not SSL/TLS versions but various types of SSL contexts which also include the usable SSL/TLS versions. This means the *_server "versions" are all SSL contexts which should be used on the server side where you usually also need a certificate. The *_client variants are for the client side of the TLS handshake, i.e. the one which initiates the TLS handshake.
Within a mail client you don't want to use any server specific SSL contexts because with these the mail client would expect the peer to start with the TLS handshake which it does not.
For more details see the man page of SSL_CTX_new which has a detailed description of what all these different contexts mean.
... allowing my users to select the TLS/SSL version they want.
While your specific implementation is wrong the idea of letting users chose the protocol version is wrong too. Instead you should just use a generic context without limitations (apart from disabling insecure versions) so that it automatically picks the best protocol version during the TLS exchange. Selecting specific protocol versions should only be done in case the peers TLS stack is broken, like for stacks which simply refuse a TLS 1.2 handshake instead of replying with TLS 1.0 in case they don't support TLS 1.2.
I'm using this example as a template in a server/client pair I wrote. I honestly don't understand all the details on how the secure connection is done. I understand the simple private/public RSA encryption. We encrypt with a public key, and only private keys can open it. Is it as simple here? (this is not the real question here)
So my question is: In my client part I used set_verify_mode(boost::asio::ssl::verify_none);. Does this jeopardize the secure connection I'm using? Is the connection still secure and encrypted?
No, it's not safe setting SSL_VERIFY_NONE. In this case if someone attack the connection the client won't be able to verify the sender's identity.
Detailed description of server and client behaviour for each flags on openssl site:
https://www.openssl.org/docs/manmaster/ssl/SSL_CTX_set_verify.html
I'm using ssl3 to connect to server. When the -change_session_version option is specified with the -reconnect, I want the session protocol to change to SSLv2 from SSLv3
This is my command: apps/openssl s_client -connect 10.102.113.3:443 -reconnect -change_session_version -ssl3
Now, I know that I should have either this code:
if(change_session_version)
s->session->ssl_version = SSL2_VERSION;
Or this code:
if(change_session_version)
s->version = SSL2_VERSION;
I don't know where to put this code though.
I have declared change_session_version as an int in ssl.h and have set it to 1 if the -change_session_version option is specified.
Please help me out!
Your question embodies a contradiction in terms. A 'session' in SSL comprises the protocol, the cipher suite, the key material, and the peer certificates. You can't change any of them without creating a new session.
EDIT Just changing a variable in a piece of local memory can't possibly accomplish anything useful. The peer won't know about it, and the other peers sharing the session on other connections won't know about it either. You have to re-handshake and negotiate a new session.
I don't think this is possible. First, SSLv2 is practically not supported anymore and most stacks don't even implement it while the others have disabled it. And then there is no support for session resumption in SSLv2 at all.
In SSL connections. As far as I understand that the the order of the cipher suit that the client offers to the server matters. How can I know what is the order of the client's offered cipher suit in my Firefox or IE browsers?
In FF, I tried to type about:config and then filtered the output to: security.ssl, I got:
Is this is the exact order that the client offers to SSL servers? Does this means, my browser prefers DHE and ECDHE over RSA key exchange because the DHE and ECDHE ciphers came first?
There is nothing in the TLS RFC that says the order matters. Specific servers may choose to honor the order provided by the client as an order of preference, but it isn't required, and neither JSSE not OpenSSL does so to the best of my knowledge.
I have a couple questions about SSL certificates.
I never used them before but my current project requires me to do so.
Question 1.
Where should you use SSL? Like I know places like logging in, resetting passwords are definite places to put it. How about once they are logged in? Should all requests go through SSL even if the data in there account is not considered sensitive data? Would that slow down SSL for the important parts? Or does it make no difference?(sort of well you got SSL might as well make everything go through it no matter what).
Question 2.
I know in smtp you can enable SSL as well. I am guessing this would be pretty good to use if your sending say a rest password to them.
If I enable this setting how can I tell if SSL if it is working? Like how do I know if it really enabled it? What happens if the mail server does not have SSL enabled and your have that boolean value enabled. Will it just send it as non SSL then?
With an SSL connection, one of the most expensive portions (relatively speaking) is the establishment of the connection. Depending on how it is set up, for example, it might create an ephemeral (created on the fly) RSA key for establishing a session key. That can be somewhat expensive if many of them have to be created constantly. If, though, the creation of new connections is less common (and they are used for longer periods of time), then the cost may not be relevant.
Once the connection has been established, the added cost of SSL is not that great although it does depend on the encryption type. For example, using 256-bit AES for encryption will take more time than using 128-bit RC4 for the encryption. I recently did some testing with communications all on the same PC where both client and server were echoing data back and forth. In other words, the communications made up almost the entire cost of the test. Using 128-bit RC4 added about 30% to the cost (measured in time), and using 256-bit AES added nearly 50% to the cost. But remember, this was on one single PC on the loopback adapter. If the data were transmitted across a LAN or WAN, then the relative costs is significantly less. So if you already have an SSL connection established, I would continue to use it.
As far as verifying that SSL is actually being used? There are probably "official" ways of verifying it, using a network sniffer is a poor man's version. I ran Wireshark and sniffed network traffic and compared a non-SSL connection and an SSL connection and looked at the raw data. I could easily see raw text data in the non-SSL version while the SSL "looked" encrypted. That, of course, means absolutely nothing. But it does show that "something" is happening to the data. In other words, if you think you are using SSL but can recognize the raw text in a network sniff, then something is not working as you expected. The converse is not true, though. Just because you can't read it, it does not mean it is encrypted.
Use SSL for any sensitive data, not just passwords, but credit card numbers, financial info, etc. There's no reason to use it for other pages.
Some environments, such as ASP.NET, allow SSL to be used for encryption of cookies. It's good to do this for any authentication or session-ID related cookies, as these can be used to spoof logins or replay sessions. You can turn these on in web.config; they're off by default.
ASP.NET also has an option that will require all authenticated pages to use SSL. Non-SSL requests get tossed. Be careful with this one, as it can cause sessions to appear hung. I'd recommend not turning on options like this, unless you really need them.
Sorry, can't help with the smtp questions.
First off, SSL is used to encrypt communications between client and server. It does this by using a public key that is used for encryption. In my opinion it is a good practice to use it for as anything that has personally identifiable information or sensitive information.
Also, it is worth pointing out that there are two types of SSL authentication:
One Way - in which there is a single, server certificate - this is the most common
Two Way - in which there is a server certificate and a client certificate - the client first verifies the server's identity and then the server ids the client's id - example is DOD CAC
With both, it is important to have up to date, signed, certificates by a reputable CA. This verifies your site's identity.
As for question 2, yes, you should use SSL over SMTP if you can. If your emails are routed through an untrusted router, they can be eavesdropped if sent without encryption. I am not sure about the 'boolean value enabled' question. I don't believe setting up SSL is simply as easy as checking a box though.
A couple people have already answered your Question 1.
For question 2 though, I wouldn't characterize SMTP over SSL as protecting the message. There could be plenty of points at which the message is exposed. If you want to protect the message itself, you need S/MIME, or something similar. I'd say SMTP over SSL is more useful for protecting your SMTP credentials, so that someone cannot grab your password.