I think you need a tutorial in how X.509 hierarchies and chains of trust work.
Consider a public and private key pair: if I have a private key and you have the corresponding public key, you can decrypt something I encrypt. This permits all sorts of interesting possibilities: If I encrypt something, and you can decrypt it to its plain text form, it establishes that it came from me, or that I somehow vouch for it (by encrypting it in the first place). Now, simply decrypting something that has been encrypted will not guarantee that what you get isn't gobbledygook. However, if what you decrypt is, somehow internally consistent, it can mitigate that possibility. So, consider an X.509 certificate. It contains, among other things, a public key, key algorithm, what the certificate can be used for, expiration timestape, and, most importantly, a SIGNATURE (and a signature algorithm). This signature is the encrypted hash (according to the specified signature algorithm), of the rest of the certificate. It is encrypted by the private key corresponding to the certificates ISSUER (which might be the same as the subject of the certificate itself, for root, or other "self-signed" certificates). Let that sink in for a bit. If you have the public key corresponding to the private key that was used TO ENCRYPT THE CERTIFICATE HASH TO MAKE THE SIGNATURE, you can decrypt that signature, and compare it to what the hash over the rest of the certificate is. If they match, you can assure yourself that the owner of the private key that "signed" the certificate vouched for its authenticity. In your case, this means vouching for all the elements of the certificate being BOUND to one another. Specifically, that the common name is BOUND to the public key in the certificate, and therefore to the owner of the corresponding private key. So, if you trust who signed the certificate (and have their public key), and verify that they signed the certificate, you can be assured that traffic from the server named in the common name will be encrypted by the private key corresponding to the public key in the certificate. This "public key of who signed the certificate" is, of course, just stored in yet another certificate. So, you can imagine a "chain" of certificates with public keys that correspond to private keys that have been used to encrypt the hashes of the contents of subsequent certificates in the chain. The chain starts with a "root" certificate who's corresponding private key encrypted the hash of the certificate to make a "self-signed" certificate. So, sending the common name in a certificate in "plain text" does not offer any means to tamper with it in transit, since, if that happened, the signature of the certificate would be wrong. All it does is reveal the common name of the site that offered the certificate. Evesdroppers can tell the site you contacted, but they can likely do than anyway via DNS, so this does not leak any extra information. Do you follow so far? So, all the server needs is its certificate (which somebody signed), and private key. It DOES NOT NEED to send the certificate that corresponds to the private key that signed it... but the browser (or other client) must have it. Otherwise you can't trust the site you reach. This is why server certificates from "well-known" certificate authorities (like Verisign. Thwaite, etc.) are so valuable: your browser already trusts the issuer (Whether this is actually a good thing, given how many such issuers there are, is debatable: would you really want to trust a Chinese certificate authority to sign the certificate provided by your American bank? Not to disparage the Chinese (the reverse situation would be just as suspect), but there the lack of legal recourse against organizations in different jurisdictions claiming a trust relationship is problematic.) Now, if all you want to do is secure traffic between two sites, you CAN have your server use a self-signed certificate, and somehow separately get that certificate to your clients (say, postal mail). Then, when that certificate is presented, you can verify it. Many home routers that provide secureed web-based administration do this: after all, if you contact the router, and it's on your desk, you can pretty much trust that your traffic to it has not been intercepted. Certificate hierarchies are designed to avoid the need to have certificates from ALL your secured correspondents: you just need to trust the few organizations that issue all the certificates you will encounter. The simple (non-self-signed) example involves a root certificate and a server certificate. But, there can be many "intermediate" certificates inbetween. SSL allows the server to send these, lest the client does not have some of them. Starting from the trusted root certificate, the client can verify intermediate certificates in turn until it finally verifies the server certificate. Has that helped at all? -----Original Message----- From: owner-openssl-us...@openssl.org on behalf of piper.guy1 Sent: Mon 4/19/2010 1:27 PM To: openssl-users@openssl.org Subject: Re: Verisign client requirements David, Sorry for my late response. (pulled in another direction for a while). But i still have a few holes in my understanding (and maybe my head!!). Here are some facts about our implementation: 1. The server does not have my root certificate. 2. I do not have the server's root certificate. 3. I do not store any server or Verisign certificates. 4. The server does not request my client certificate. So based on what you said below, and knowing the above: > This is precisely what a browser does. Again, using the > "https://www.amazon.com" example, OpenSSL takes care of getting the > certificate from the server, making sure the certificate is valid, checking > that the server owns the certificate, and making sure the certificate's > trust chain has a root CA that is on your trusted list. However, > www.badguys.com could also pass all those tests. .....how does OpenSSL (or can our implementation of OpenSSL): - make sure the certs are valid, - the server owns the certificate - make sure the certificate trust chain has a root CA. > So that leaves you to check > the common name on the certificate and make sure it's the *right* name -- > that is, the server you wanted to reach. I also noticed when i sniffed the wire that the common name field is in clear text. What's the point of verifying that? Based on the 4 points above, would you say that our implementation is not very strong? I don't have the security expertise to challenge the server guys so it's basically status quo, which my gut tells me is not very strong. thanx /carl h. On Mon, Apr 5, 2010 at 5:04 PM, David Schwartz <dav...@webmaster.com> wrote: > > Piper.guy1 wrote: > >> Hi, >> >> Please understand I'm a newbie to security if my question sounds >> rather elementary. >> >> The embedded product I'm working on requires a secure connection to >> our server that uses a Verisign certificate to authenticate. I've been >> porting the OpenSSL examples from the O'Reilly publication so far and >> I have been successfully able to make a secure encrypted connection >> without authentication. (example client1.c). Our next step it to >> implement authentication using a Verisign cert. > > Usually, when people talk about "authentication", they mean the server > authenticating the client. The client always makes sure it has reached the > correct server. I presume, what you are talking about is the same check that > every browser does. When you punch "https://www.amazon.com" into your > browser, your browser makes sure the server you reach presents a certificate > for "www.amazon.com" that is signed by a CA your browser trusts -- and then > it makes the server prove it knows the private key corresponding to the > public key in that certificate. > > Is that all you're trying to do? > >> 3rd party CA's are talked about in the book very nicely but the focus >> is on the server, and very little is discussed regarding what the >> client needs to implement, unless I'm not reading in the right place, >> or there's very little else for the client to do. >> >> It would seem that I would have to implement much of example >> client2.c; or essentially call: >> >> 1. SSL_CTX_load_verify_locations() with the trusted certificates file > > Correct. And the trusted files should include the root certificates your > client trusts. It must include the Verisign root certificate that your > server's trust chain starts with (or ends with, depending on how you look at > it). > >> 2. SSL_CTX_set_verify() with the SSL_VERIFY_PEER flag set >> >> Do I have to add anything else to the trusted certificates file or >> will OpenSSL magically know to authenticate with Verisign? >> >> Is this all I need to do? > > The problem with this is it will wind up accepting any certificate whose > trust chain's root is one of your trusted certificates, yours or not. The > best solution to this problem is to confirm that the certificate presented > has as its common name the name your client is trying to reach. > > This is precisely what a browser does. Again, using the > "https://www.amazon.com" example, OpenSSL takes care of getting the > certificate from the server, making sure the certificate is valid, checking > that the server owns the certificate, and making sure the certificate's > trust chain has a root CA that is on your trusted list. However, > www.badguys.com could also pass all those tests. So that leaves you to check > the common name on the certificate and make sure it's the *right* name -- > that is, the server you wanted to reach. > > DS > > ______________________________________________________________________ > OpenSSL Project http://www.openssl.org > User Support Mailing List openssl-us...@openssl.org > Automated List Manager majord...@openssl.org > ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org