Increase the key size for Jingle XTLS, enable TLS 1.1 and TLS 1.2
problem
- The Jingle XTLS implemented Gajim uses only 1024 bit RSA key. This is quite weak.
- The Jingle XTLS communication in Gajim support only TLS v1, not TLS v1.1 and TLS v1.2
- The private key ~/.config/gajim/localcert.pkey is has permission 0644, it's should have only 0600
- MD5 is used as certificate signature algorithm, MD5 in X509 certificates was broken
analysis
It's important to make Jingle XTLS stronger, in future it could be used to authenticate VoIP encryption, ZRTP (XEP-0262) or DTLS (XEP-0320).
Replace the MD5 signature algorithm with SHA-1. SHA-2 256 bit would be better but it's not supported in older OpenSSL versions.
Most web servers are currently using 2048 bit RSA keys. 3072-bit RSA keys should be equivalent in strength to 128-bit symmetric keys. My personal favorite is 4096 bit RSA, this gives enough reserve into future. https://en.wikipedia.org/wiki/Key_size
TLS 1 and OP_SINGLE_DH_USE, the same as in https://python-nbxmpp.gajim.org/ticket/8
enhancement recommendation
diff -r 0861ddcb7fab src/common/jingle_xtls.py
--- a/src/common/jingle_xtls.py Wed Oct 30 11:58:18 2013 +0100
+++ b/src/common/jingle_xtls.py Sun Nov 03 23:33:57 2013 +0100
@@ -92,7 +92,10 @@
"""
constructs and returns the context objects
"""
- ctx = SSL.Context(SSL.TLSv1_METHOD)
+ ctx = SSL.Context(SSL.SSLv23_METHOD)
+ flags = (SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3 | SSL.OP_SINGLE_DH_USE)
+ ctx.set_options(flags)
+ ctx.set_cipher_list('HIGH:!aNULL:!eNULL')
if fingerprint == 'server': # for testing purposes only
ctx.set_verify(SSL.VERIFY_NONE|SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
@@ -174,12 +177,12 @@
pkey.generate_key(type, bits)
return pkey
-def createCertRequest(pkey, digest="md5", **name):
+def createCertRequest(pkey, digest="sha1", **name):
"""
Create a certificate request.
Arguments: pkey - The key to associate with the request
- digest - Digestion method to use for signing, default is md5
+ digest - Digestion method to use for signing, default is sha1
**name - The name of the subject of the request, possible
arguments are:
C - Country name
@@ -201,7 +204,7 @@
req.sign(pkey, digest)
return req
-def createCertificate(req, (issuerCert, issuerKey), serial, (notBefore, notAfter), digest="md5"):
+def createCertificate(req, (issuerCert, issuerKey), serial, (notBefore, notAfter), digest="sha1"):
"""
Generate a certificate given a certificate request.
@@ -213,7 +216,7 @@
starts being valid
notAfter - Timestamp (relative to now) when the certificate
stops being valid
- digest - Digest method to use for signing, default is md5
+ digest - Digest method to use for signing, default is sha1
Returns: The signed certificate in an X509 object
"""
cert = crypto.X509()
@@ -233,10 +236,12 @@
and '.cert' extensions
CN : common name
"""
- key = createKeyPair(TYPE_RSA, 1024)
+ key = createKeyPair(TYPE_RSA, 4096)
req = createCertRequest(key, CN=CN)
cert = createCertificate(req, (req, key), 0, (0, 60*60*24*365*5)) # five years
- open(filepath + '.pkey', 'w').write(crypto.dump_privatekey(
+ private_key_file = open(filepath + '.pkey', 'w')
+ os.chmod(filepath + '.pkey', 0600)
+ private_key_file.write(crypto.dump_privatekey(
crypto.FILETYPE_PEM, key))
open(filepath + '.cert', 'w').write(crypto.dump_certificate(
crypto.FILETYPE_PEM, cert))