Opened 15 years ago

Closed 10 years ago

#141 closed defect (fixed)

use better SSL certificates

Reported by: Brian Warner Owned by: Brian Warner
Priority: major Milestone: 0.8.0
Component: unknown Version: 0.4.1
Keywords: security Cc: davidsarah

Description (last modified by Brian Warner)

I was disappointed to see that a default foolscap certificate is using MD5 and RSA with 1024-bit pubkey keys, both of which are definitely behind the curve as far as modern crypto practices go. (several collisions have already been found for MD5, although what Foolscap really cares about are preimage attacks, and as far as I've heard nobody's found one of those yet):

% python
>>> import foolscap
>>> foolscap.Tub(certFile="foo.pem")
<Tub id=lj37uywdnuoeghujdjnu7l5sxcxmzaoz>
>>> ^D
% openssl x509 -in foo.pem -text
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 132 (0x84)
        Signature Algorithm: md5WithRSAEncryption
        Issuer: CN=newpb_thingy
        Validity
            Not Before: Oct  7 23:02:55 2009 GMT
            Not After : Oct  7 23:02:55 2010 GMT
        Subject: CN=newpb_thingy
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
 ...

I was expecting a modern OpenSSL to choose better defaults (this was tested both on my OS-X 10.6 box and on a recent debian/sid system).

I don't know offhand how to tell python-openssl to use something better.

Change History (9)

comment:1 Changed 13 years ago by zancas

To inspect the contents of a <tub>.pem x.509-ish file one can use:

openssl asn1parse -in <tub>.pem

Interestingly when I use this tool on a .pem in an incident-gatherer tub I get the following error:

Error in encoding
17525:error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long:asn1_lib.c:150:

However if I make a new file that contains only the section:

 -----BEGIN CERTIFICATE---- --> -----END CERTIFICATE-----

i.e. excluding the RSA private key, this parser emits no errors.

There's a -i flag that makes the output of asn1parse slightly more readable, and the --strparse <OFFSET> option seems like it might be handy. Of course, see:

man asn1parse

for details.

comment:2 Changed 12 years ago by davidsarah

Cc: davidsarah added
Owner: set to Brian Warner

comment:3 Changed 10 years ago by Brian Warner

Description: modified (diff)
Milestone: undecided0.8.0

I just tested this on my modern (OS-X 10.9) system, and my debian/sid box, and both are still getting the same kind of certificate. Time to fix this.

comment:4 Changed 10 years ago by Brian Warner

Let's also improve the runtime SSL negotiation: specifically to avoid falling back to SSL3 and things like that.

comment:5 Changed 10 years ago by Brian Warner

Ok, with Daira's help I was able to improve the certs to 2048 bit SHA256.

% python -c "from foolscap.api import Tub; Tub(certFile='t.pem')"
% ls -l t.pem
-rw-r--r--  1 warner  staff  2652 Mar 31 10:54 t.pem
% openssl x509 -text -in t.pem
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=newpb_thingy
        Validity
            Not Before: Mar 31 17:54:07 2015 GMT
            Not After : Mar 30 17:54:07 2016 GMT
        Subject: CN=newpb_thingy
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
...

Landed in a65047a.

Version 0, edited 10 years ago by Brian Warner (next)

comment:6 Changed 10 years ago by davidsarah

https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2400 might be another reason to release this fix soonish, if my current theory about that bug (that it is due to using MD5) is correct.

comment:7 Changed 10 years ago by davidsarah

In addition to the change in a65047acea2c7034cbbaf94365c608e34827c9c4, this change in createCertificate is apparently needed in order to fix https://tahoe-lafs.org/trac/tahoe-lafs/ticket/2400:

- req = keypair.certificateRequest(dn)
+ req = keypair.certificateRequest(dn, digestAlgorithm="sha256")

(Thanks to LeastAuthority.com user Gabe for working this out.)

comment:8 Changed 10 years ago by Brian Warner

Good catch.. landed in 2a76437af31c97bdbfdc65ffda4d0cb60a97684a .

Some other notes from the openssl experts I met at pycon:

  • it'd be nice to generate v3 SSL certificates instead of the default v1. The change for that must go into Twisted, in twisted/internet/_sslverify.py, KeyPair.signRequestObject, to do a cert.set_version(2) (probably) right after the cert = crypto.X509(). We can't do this from the Foolscap layer.
  • it'd also be nice to require the connection use TLS1.0 or TLS1.1 or better, and reject the older protocol versions. Nobody knew how to do this.

comment:9 Changed 10 years ago by Brian Warner

Resolution: fixed
Status: newclosed

Ok, we've fixed this as much as possible for now. v3-format certs will require a change to Twisted. We'll improve the connection version (as opposed to the certificate version) in a different ticket.

Note: See TracTickets for help on using tickets.