Tag: ssl

 

What's in a certificate?

The principle of public-key cryptography is fairly simple to get.

  • Alice has a public/private keypair.
  • Alice gives the public key to Bob.
  • Bob encrypts some data for Alice using the public key.
  • Bob sends the data to Alice, who can decrypt it using her private key.

There’s also some other stuff about multiplying large primes, and how difficult it is to reverse that. But how on earth does this relate to certificates in the real world? If you click on that padlock in your browser, how does that relate to the above scenario?

For this demonstration, let’s use OpenSSL, as it’s commonly available. I’m going to make a “self-signed” key pair. More on that in a moment.

% openssl req -out cert -newkey rsa:2048 -keyout key -x509
Generating a 2048 bit RSA private key
......................+++
.............+++
writing new private key to 'key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:GB
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Brighton
Organization Name (eg, company) [Internet Widgits Pty Ltd]:happygiraffe
Organizational Unit Name (eg, section) []:.
Common Name (eg, YOUR name) []:Dominic Mitchell
Email Address []:dom@happygiraffe.net
hdm-macbookpro% ls -l
total 16
-rw-r--r--  1 hdm  5000  1554 19 Mar 17:51 cert
-rw-r--r--  1 hdm  5000  1751 19 Mar 17:51 key

So, what do we have here? Let’s look at the key first.

% openssl rsa -in key -noout -text
Enter pass phrase for key:
Private-Key: (2048 bit)
modulus:
    00:b4:73:f1:5d:53:e1:ca:e9:9b:5a:02:14:7d:d4:
    …
publicExponent: 65537 (0x10001)
privateExponent:
    00:8a:77:e1:81:1c:e9:c9:1b:a2:f2:d9:5f:c2:02:
    …
prime1:
    00:dd:cc:63:f6:08:0d:dc:18:ca:73:1a:04:17:7c:
    …
prime2:
    00:d0:47:6a:b7:9a:35:1c:5f:a6:a5:46:f0:ec:3e:
    …
exponent1:
    57:76:08:98:f5:16:1a:0b:80:91:a0:d9:aa:35:25:
    …
exponent2:
    07:60:50:1e:3a:7e:e1:07:5e:2e:82:49:ac:04:36:
    …
coefficient:
    00:8b:79:fb:33:d1:e6:08:f0:e9:ac:ef:8c:9c:0e:
    …

Hmmm, lots of maths stuff. What’s in the certificate?

% openssl x509 -in cert -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            f4:00:d8:ff:2b:10:b4:fe
        Signature Algorithm: md5WithRSAEncryption
        Issuer: C=GB, L=Brighton, O=happygiraffe, CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
        Validity
            Not Before: Mar 19 17:51:38 2010 GMT
            Not After : Apr 18 17:51:38 2010 GMT
        Subject: C=GB, L=Brighton, O=happygiraffe, CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
                    00:b4:73:f1:5d:53:e1:ca:e9:9b:5a:02:14:7d:d4:
                    …
                    09:3b
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                56:F8:A1:FC:C0:B0:D3:5A:74:A2:2B:BC:91:1D:67:B1:84:42:88:B8
            X509v3 Authority Key Identifier:
                keyid:56:F8:A1:FC:C0:B0:D3:5A:74:A2:2B:BC:91:1D:67:B1:84:42:88:B8
                DirName:/C=GB/L=Brighton/O=happygiraffe/CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
                serial:F4:00:D8:FF:2B:10:B4:FE

            X509v3 Basic Constraints:
                CA:TRUE
    Signature Algorithm: md5WithRSAEncryption
        ae:82:88:3b:0b:85:4b:0f:6d:54:b0:27:ac:d1:ec:4c:b1:70:
        …
        dc:e5:26:d5

There’s a great deal of useful information here. Note that “Issuer” and “Subject” fields are identical. This is what I meant by “self-signed” earlier. For a purchased certificate, the issuer would be somebody like Verisign or Thawte. Also for a certificate that’s being used for an SSL server, the CN field in the subject would have to match the hostname of the site it’s serving.

In the middle, under “Subject Public Key Info” there is some of the same information that’s present in the key (Modulus and Exponent). But there’s a lot that isn’t (this is good — you want to keep the private key private).

What’s that signature? Well, it’s a way of ensuring that the contents of the certificate can’t be tampered with. Otherwise, somebody could just alter the Subject Public Key Info to point to a different key that they control. It assures the integrity of the certificate. Think of it like a secure wrapper.

So, we’ve got a certificate with public key information inside, but how is actually used in practice? OpenSSL will let us simulate a client and a server. Open up a terminal window and run:

% openssl s_server -cert cert -key key -msg
Using default temp DH parameters
Enter PEM pass phrase:
ACCEPT

Open another command line and run:

% openssl s_client -debug -connect localhost:4433 -msg
CONNECTED(00000004)
…
>>> SSL 2.0 [length 0074], CLIENT-HELLO
…
<<< TLS 1.0 Handshake [length 004a], ServerHello
…
<<< TLS 1.0 Handshake [length 045c], Certificate
…
depth=0 /C=GB/L=Brighton/O=happygiraffe/CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=GB/L=Brighton/O=happygiraffe/CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
verify return:1
…
<<< TLS 1.0 Handshake [length 018d], ServerKeyExchange
…
<<< TLS 1.0 Handshake [length 0004], ServerHelloDone
…
>>> TLS 1.0 Handshake [length 0046], ClientKeyExchange
…
>>> TLS 1.0 ChangeCipherSpec [length 0001]
…
>>> TLS 1.0 Handshake [length 0010], Finished
…
<<< TLS 1.0 ChangeCipherSpec [length 0001]
…
<<< TLS 1.0 Handshake [length 0010], Finished
---
Certificate chain
 0 s:/C=GB/L=Brighton/O=happygiraffe/CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
   i:/C=GB/L=Brighton/O=happygiraffe/CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
---
Server certificate
-----BEGIN CERTIFICATE-----
…
-----END CERTIFICATE-----
subject=/C=GB/L=Brighton/O=happygiraffe/CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
issuer=/C=GB/L=Brighton/O=happygiraffe/CN=Dominic Mitchell/emailAddress=dom@happygiraffe.net
---
No client certificate CA names sent
---
SSL handshake has read 1670 bytes and written 252 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 422BC3AE9F6B11C32770C6A6DB8B915713754C00694FCCF6BA37FE14A3D5C087
    Session-ID-ctx:
    Master-Key: 32895E90044DFE72B8CAEC4B7D4E14DF9969109AFE9F0504C69CA4B9CB9259E177C85B498F9F850EBF5866DF47A45B17
    Key-Arg   : None
    Start Time: 1269245236
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---

This is really verbose (it is a debugging tool), so I've removed much of the output. But it shows the important steps in the SSL transaction. Of particular interest is the line near the end stating the Master-Key. This reveals the truth behind public key crypto: it's expensive enough that it's used for just long enough to exchange a regular two-way encryption key between the two peers. The public key information in the certificate is only used to encrypt a single message to the server (ClientKeyExchange) containing the private key to use for this session.

Of course, there's a lot more to SSL connections than this. I've obtained most of this from SSL & TLS Essentials, which has a very detailed breakdown of precisely what's happening.

Please don't rely on the above in any way — it's just my interpretation. But it does seem useful to explore certificates a little bit more.

del.icio.us api change

I’ve just been caught out by the del.icio.us api change (they’ve just switched off the old api). This broke the backup script I use. It’s a nice script, it downloads each days bookmarks into a sqlite database, ready for reuse.

Anyway, this is the patch I wrote to make it use the new api (over SSL) instead. BTW, top marks to the del.icio.us people for using basic auth instead of coming up with their own scheme. Basic auth + SSL is a really nice, simple way of doing things.

  --- /home/dom/delicious-backup.rb.orig    Fri Aug 11 09:00:39 2006
  +++ /home/dom/bin/delicious-backup.rb    Fri Aug 11 09:09:19 2006
  @@ -26,11 +32,29 @@
                'values (?, ?, ?, ?, ?);'
   insert_tag = 'insert into tags (hash, tag) values (?, ?);'

  -xml = Net::HTTP.start('del.icio.us') { |http|
  -    req = Net::HTTP::Get.new('/api/posts/all', {'User-Agent' => agent})
  +# https://api.del.icio.us/v1/posts/get
  +require 'net/https'
  +http = Net::HTTP.new('api.del.icio.us', 443)
  +http.use_ssl = true
  +http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  +xml = http.start { |conn|
  +    req = Net::HTTP::Get.new('/v1/posts/all', {'User-Agent' => agent})
       req.basic_auth(user, pass)
  -    http.request(req).body
  +    resp = conn.request(req)
  +    raise resp.inspect unless resp.kind_of? Net::HTTPSuccess
  +    resp.body
   }
  +
  +Dir.chdir(ARGV[1] || ENV['HOME'] + '/libdata/del.icio.us')
  +
  +# Clean anything over 30 days.
  +thirty_days_ago = Time.now - (30 *(24*60*60))
  +Dir["*.db"].each do |name|
  +    f = File.new(name)
  +    if f.mtime < thirty_days_ago
  +        File.unlink(name)
  +    end
  +end

   db_name = ARGV[0] || Time.now.strftime("%Y-%m-%d.db")
   SQLite3::Database.open(db_name).transaction { |db|

That’s also got my backup expiry bits in, which is handy, but could probably be done better. BTW, that ruby idiom of indexing the Dir class to run a glob is freakish.