Secure communication between applications using SSL Certificates
I like the answer from this.josh, but there was a couple of points I wanted to add:
- TLS does not use the certificate for protecting the channel - that is done by a negotiated symmetric key. TLS uses certificates (server or client) authentication and key encipherment.
- I agree that a certificate used for encryption should not be the same as the certificate used for authentication - however, in this case, I think it's safe to say the certificate used for TLS is used for authentication, not encryption. It's true that if you dig down into it, there is key encipherment being done with the certificate, and I'm sure that if you get a high end system, you will end up with people who disagree with me on this, but it seems like overkill to go through a challenge/response protocol on top of TLS for many use cases.
- implied in the previous answer, but I'll say it point blank - TLS by default is usually server authentication only. To get client authentication, you will need to turn on a switch for that, and in the process you'll specify:
- what credentials are OK for client auth - for example digital certificates.
- what to do to check the credential - for example, verify against a trusted Certificate Authority that signed the certificate, and verify against an OCSP or CRL source for certificate status - this is a whole area on PKI, and I think if you dig in this Stack Exchange you'll find more on this.
In general, checking all factors of a provided certificate on both the client and the server is the best path to the assurance that the entity connecting to this channel is the entity it says it is. Typical mechanisms include:
- Trusted signer - certificates are generally signed by a Certificate Authority (CA). That Certificate Authority is trusted to verify the requestor prior to certificate issuance. Most systems that have a widely distributed need for trust, trust a set of CAs to issue credentials. They do this by keeping a set of CA certificates on hand, so that when an end entity shows up with a trusted CA signed certificate, they can check that one of the approved (known) CAs signed the cert.
- Status - when a CA signs a cert, it also takes responsibility for keeping the status up to date - it does this by issuing CRLs (Certificate revocation lists) which may or may not be rendered via OCSP (a request/response protocol) for fast querying. Then endpoints verify the status of the certificate, when it's received, to make sure that the certificate is still valid according to its issuing CA.
- Self signed certificates - if a certificate isn't signed by a CA, it's self-signed. This it the super-cheap way to do it, but it makes configuration a bear. Self-signed certificates assert their own goodness, so the party (application) verifying it has to manually trust each self-signed certificate individually by keeping a copy of each certificate on hand. Cheap, and good enough if you have a very small installation, but it scales abysmally.
- Validity - in all cases, certificates are valid from a start date to an end date, and should be reviewed to make sure of current validity.
Authentication v. Authorization
Authentication - is the entity who it says it is? This is true as long as the credential is a valid proof of identity. Even if I'm 16, my driver's license is valid if it was properly issued by my state of residence. It doesn't mean I'm authorized to buy liquor, however (if I live in the U.S., at least, I have to be 21).
Authorization is the entity allowed to do what it wants to do? I'm authorized to buy liquor if I'm over 21. Technically, my over-21ness is all I need, but I prove that with authentication - my driver's license or passport or state issued id.
It sounds like you want both. You want each side to prove its identity (authentication) and be of a certain restricted group (created by your company). So you need more than just TLS client authentication - you need some added way of checking criteria to verify authorization.
I can think of a couple ways to approach that:
set up a trusted users list - with PKI, the typical way is a list of subject DNs (distinguished names) for each client or server. The scalability is directly related to where you store this list - a public store - like an LDAP server - is a good bet, so that all servers can check a common location.
make sure there be a quality in your certificates - the organization value in a DN comes to mind - it's typically the value that describes the organization the entity comes from. For example, my personal digital certificates have my company's name as the "O" value because my company paid for me to get them. You can then construct some added code (or in a very smart server, you can just configure it...) to check that "O=your company" - and you're good - so long as you can assure that no one else can make certificates with your company's name in the "O" value. One way to do that is some of the higher end commercial certificate authorities, where you set up an agreement and an account with that CA provider, and you have an appointed approval person in your company to do the paperwork. That person certifies that each request for a certificate comes from your company before the CA will make a certificate. You can do the same thing running your own CA - essentially you're trading off time vs. money.
WARNING: I'm glossing over a lot of detail here. Figuring out "how secure" authentication and authorization controls should be and how they should be administrated is a full time job. In fact, it's a whole industry. What I'm throwing up here is the grass roots concepts for a bare bones effort. If you told me that you were putting together something that was going to protect millions or billions of dollars of corporate investments, or human life, or the state of the world as we know it - I would tell you to contact me offline and I have a nice team of smart people handy who can take this problem off your hands... for a fee. The whole area becomes a chicken and egg scenario pretty fast, as every communication and procedure around checking this stuff needs to be handled with care, since any system is only as strong as its weakest link. What I'm throwing in here assumes that you don't have anything huge, you're mostly working on a newish system that needs just a bit of protection - the equivalent of throwing up a nice gate around your house. Not a gate, guard dogs, security cameras, and a big guy with a spiked club. :)
Now... key storage
Key storage has two main elements:
- How safe does it have to be from attack?
- How does it need to be accessed?
"Safe" is often rated in FIPS compliance levels - it's a way of testing key storage mechanisms and that they meet certain sets of escalating security requirements. The low end is software storage - the key uses one of several commercially supported storage mechanisms and it sits on your hard drive (Price = free or the price of a tiny bit of memory on your hard drive). The high end is a big, expensive box (an HSM - hardware security module) that will hold your key in such a way that no one can get the key out of the box... ever... and when they try, if they try too hard, the box will zerioze itself, erasing the key. There's levels in between.
How much safety you want to pay for is entirely a risk/cost decision. You have to calculate what you have to loose vs. what you want to pay.
"How to access" has a couple of elements:
- Software keys are easy to access on the box - there's a couple of commercially supported ways of storing them and most servers support most storage mechanisms. PKCS12, and JKS are two examples.
- Hardware keys are typically accessed by the PKCS 11 protocol (but there are others), most high end servers have this built in, but sometimes you need extensions to handle this or APIs for custom built code. Also, you have a chicken/egg problem - you usually need a password to get access to your HSM - where and how you store that password is another area of security.
- for clients, you also have the mobility problem. If "client" is a fixed point - you have the same HW/SW options as for servers, but if "client" means a human, then you also need to think about user mobility and compatibility with any GUI mechanism (for example, a browser). It still boils down to HW/SW, but often the HW element is called a "token", because remove-ability becomes a key feature.
In all cases, you can store your certificates just about anywhere - they are public information that can be distributed far and wide. The critical element is your private key - which must be stored in a place that only the entity using it can get to.
Who can use a single certificate
It depends on how you are storing your keys and what risk you are willing to accept. A key on a network accessible HSM could technically be used by a bank of servers, which would let all servers look like one server (pretty cool for a web app). But if you need to have proof of exactly which client or server did a specific action, then you must have 1 certificate per entity. Also, you can only revoke a certificate - so you want a level of separation that if you believe a key store had been compromised, you could disable just one thing.
Generally, it's a checkpoint if you find yourself putting the private key in multiple places - that's a serious risk and a good indicator that you want to get another certificate. From there, the level of separation is, IMO, mostly a matter of what level you want to track and any other needs you have for controlling access.
Yes, you likely want to use Transport Layer Security (TLS) the replacement for Secure Sockets Layer (SSL), since it is a well used and reviewed network communications security. The certificates part is a public key infrastructure which involves the generation, distribution, user, and retirement of public/private key pairs and derivative data.
It sounds like you are building a prototype for a client application that will only talk to an authenticated server. Authenticating a remote server is different from just protecting the communications channel. Even if you wind up using certificates to authenticate the server, you should not use the same certificates to protect the communications channel and to authenticate the server.
One method of authentication is a challenge response protocol. A common challenge response protocols is Secure Remote Password (SRP). SRP is accessible in many languages and platforms.
"Should every application have its own certificate?" It depends on whether you need to uniquely authenticate each client or not. If you decide that you do need unique authentication, then you need to understand the burden of keying. The number of keys you need scales directly with the number of clients. For ten clients this may not be a burden, but for ten-thousand it is challenging.
You will need to answer:
- Who will generate the keys?
- Who will sign the keys: will you use a CA or make your own CA?
- How will the keys be distributed?
- How will keys be invalidated?
- What will the key validity period be?
- How will you handle key update, recovery, and replacement?
"Where are the certificates stored?"
For most operating systems and platforms there are built in key storage mechanisms.
- Java Key Store
- Windows CryptoAPI
- OpenSSL gives you PKCS 11 and 12
- Linux has GPG, LUKS, dm-crypt, etc.