Protecting ECDH against MITM attacks - security

I am working on a project that requires an ECDH key exchange. I am trying to understand how to protect against MITM attacks. I can sign the public key and send a signature along with the public key transfer to ensure that the key has not been tampered with but that doesn't stop a MITM attack from just doing the same thing. I understand that the key exchange must be verified somehow by a third party but I'm having a hard time understanding how it is that a third party can be the solution assuming that someone can do an MITM attack. Why couldn't they just do an MITM on the third party verification too? Is there really a fail proof way of completely eliminating all possible MITM attacks without some kind of pre-known by both parties?

You need a¹ trusted third party to sign both keys.
Without any knowledge or assertions about the identity of the intended partner, there's simply no way to distinguish him² from anyone else.
¹ one or multiple
² Bob

In a PKI system, "certifying authorities" are an important part of the infrastructure. Certifying authorities sign the public key and the identifying information, so that you know the corresponding private really belongs to the purported identity. This is true for EC keys just as it is for RSA.
By the way, I've looked for CAs that issue EC certificates, and apparently they aren't in practical use.
Most people obtain certificates for their certifying authorities as part of their operating system or security application. They trust these certificates implicitly. There are several dangers here, though.
First, most users don't have an effective way to verify the integrity of these certificates. This is a pretty hard problem, because, at the root of it, you have to have a 100% trustworthy channel for the verification—channel between the authority and the user with which an attacker cannot tamper. When a user downloads a new browser with an collection of root certificates, he can't know that the software wasn't tampered with in transit, or even built with a bogus CA certificate in the collection.
Even if the certificate collection is received intact as the provider intended, there have been questions raised about the integrity of many certifying authorities included by default in popular software. For example, some have pointed out that telecommunications companies in states that have been linked to terror sponsorship have their certificates included in popular browsers. Any trusted authority can issue a certificate for any domain name, and a browser will accept it without question.
In short, no, there is no way to establish a secure channel without first sharing some information on a secure channel. The benefit of PKI and asymmetric cryptography is that one exchange on a secure channel (the receipt of a trusted authority's certificate) permits the establishment of secure channels with many parties. But you have to bootstrap the system somehow.

It sounds like you are heading down a path of rolling your own crypto protocol. Don't do that. It's a bad idea. It leads to insecure systems.
Instead, use SSL or TLS. That is designed to take care of the subtle issues in designing this kind of crypto protocol -- and it has been well-vetted. You'll need a way to verify the other endpoint's certificate. You could use a certification authority, or in some cases it might be feasible to hardcode the public key of the entity you expect to talk to.
You may get better answers if you ask on the Crypto stack exchange.

Related

How to securely transfer from an old private key, to a new one?

I can sign the new (public) key with the old (private) key to securely transfer from one to the other. But far as I can tell, there's nothing stopping anyone who gets the old key from signing a different new key as official, even much later after I've given the old one up.
If I revoke the old private key, nobody can make that bogus signature, which is good. But doesn't revoking a key mean its signature of the new one would be invalidated? (As well as every single signature it's made?)
So someone who knows me as "Alice" would be able to tell I'm the same, even if I'm "Bob." But then they see "Alice"'s revocation, in which case they have to throw all of their knowledge about me away, whether Alice or Bob?
The usual way to deal with this is to use a different key for signing keys and for signing “useful” data.
The data signing key lives on an online server where it's invoked automatically, and thus is at risk of misuse. This key is rotated regularly. In principle, it wouldn't need to be rotated: just revoke it if something bad happens. But in practice revocation is hard: it's often difficult to ensure that every party that relies on the signatures will see the revocation message in a timely way. Expiration ensures that even if a party doesn't see the revocation message, it won't keep accepting compromised signatures for long.
The key signing key lives on an offline server with stringent access control, and since it's a lot better protected, it has a very low risk of being compromised.
A system with keys that sign other keys is called a public key infrastructure. Many systems have multiple levels of signing keys. The best known PKI ecosystem is the one used for HTTPS, with servers having a certificate signed by an intermediate certificate authority, which in turn has a certificate signed by another CA until you reach a root CA. Intermediate CAs are online, but run specialized systems which do nothing but sign certificates. The keys to root CA certificates are split among multiple employees who all get together into a vault with no Internet connection once every few years to generate a new intermediate key.
Running your own CA with OpenSSL is not trivial, but it's doable, and you'll find many tutorials on the web.

Adding a signature even over HTTPS

I am creating a webservice that comunicates over HTTPS.
Security is very important for me, as I cannot accept modified data, so I am thinking about adding a message diggest (signature) to check integrity... but is it needed having it over HTTPS?
HTTPS already has sufficient signing to prevent accidental modifications.
A straight message digest with no secrets provides no protection against deliberate tampering. An active man-in-the-middle attacker could easily replace the digest with their own value, recalculated to match any alterations they made.
For a signature to have value against tampering it must have been created using a secret key on the sender, and the signature must be verifiable on the receiver, which means you must have a way to pre-exchange keys between parties before use.
For the case where the client is a general purpose web browser there is no channel to do that, other than transferring it over HTTPS at which point that interaction is just as vulnerable to man-in-the-middle attacks and you gain nothing. This is a bootstrap problem.
For the case where you have a custom application client you have distributed to your users through a channel more trusted than HTTPS (eg you physically handing them copies of the code), then yes, adding a server-to-client signature based on public key crypto could theoretically provide some value. But rolling your own crypto is prone to implementation errors and best avoided.
What's the attack you're trying to counter here, that HTTPS together with the commercial CA infrastructure doesn't address well enough?
If your concern is that the PKI of commercial CAs is historically prone to occasional fraudulently-issued certificates and state-level spying, then a much simpler way of defending against that would be to run your own private CA for application use, and have your client accept only certs issued by that CA (and not the certificates built into the system like Verisign et al).
Whether through running a CA, or ad hoc signature checking, running your own PKI securely and effectively is a bunch of ongoing overhead. Be sure the public commercial PKI really can't meet your needs before going that route.

Benefits in security to a CA signed SSL certificate

This is just a general question regarding the debate between self-signed certificates and CA certificates...
I understand the benefits for a CA certificate due to the avoided warnings generated in most browsers, but how does a CA certificate benefit actual security? I commonly hear the biggest threat is man-in-the-middle attacks, and while I understand this threat using a self-signed certificate, I don't understand how a CA certificate prevents this. I know CAs perform their own security algorithms couldn't the same algorithms be used on self-signed certificates?
I guess I'm just a little irritated by the big business revolving around the need for CA certificates but can't seem to find anything different about them other then these supposed additional security checks they perform. Is there anything a CA can provide from a security point-of-view that self-signed certificates cannot?
Spoofing. If the other party fakes a self-signed certificate, you have no way to check this. In order to check that you have received the valid certificate and not a forged one, you need third-party check which can not be easily spoofed. This is done by carrying the list of root CA certificates (and some intermediate certificates) with your client-side software (Windows includes such certificates for you and major browsers do the same) and verifying the certificate you receive from the server using those CA certificates. With self-signed certificates such verification is not possible.
Of course, you can carry the self-signed certificate with your client application (and this is what some developers do, especially for in-house applications) but this doesn't work with browsers.
The difference isn't in the algorithm, it's in whether people trust the certificate authority or not.
The point of a certificate is to verify that you are making the connection with whoever it is that you intend to make the connection with.
If I say to you "I'm the right server, trust me on this", you may choose not to believe me (after all, you don't know me).
If I say to you "I'm the right server, and I have a certificate to prove it", you could say "ok, and who gave you this certificate?" If my reply is "Joe from around the corner", you may still choose not to believe me.
But if I say "I have a certificate, and you can confirm it with a third party that you trust", you may decide that this is a good proof of identity.
How you confirm it is what the standard is all about (e.g. as described in RFC 5280). But that's just technicalities. You could use the exact same algorithm for a certificate that originated from VeriSign and for a certificate you generate yourself.
The real question is about trust: do you trust whoever is giving you the "proof of identity". We trust VeriSign enough to allow any proof of identity from them to be accepted by every browser. Should we trust individuals that generate their own self-signed certificates? We might do in some cases (in which case you can install their certificates in your browser manually), but not as a general rule.

Can I use a self-signed SSL certificate for commercial purposes?

I'm making a server-client to use ssl for sign up and login process.
(and this is for iphone if it matters)
I just started looking at what ssl is and how to use it, and
saw there is a certificate in the process which can be bought or self-signed.
If I use self-signed certificate in web server, web browser would alert that cert is self-signed, that I understand.
But what would happen if I use self-signed certificate in regular application with tcp(not http), specifically iphone.
I just want to make the signup/login
info(their password) to be secure,
and hoping that using self-signed
certificate would be ok for this
purpose. But I also need to make
sure this won't cause "not trusted
certificate - alert" type of
interruption when used in application
other than a web browser.
Edit
I understand that "not trusted certificate alert" is saying client shouldn't trust this server.
But in my situation, client doesn't need to authenticate with the server.
The server just needs to get client's password in a secure way.
To answer your question: You can, but you shouldn't!
First, using SSL only for authentication isn't secure at all. The authentication process probably produces some kind of session (e.g. cookie) which is then transfered without encryption. Therefore, the session can be stolen (see Session hijacking).
Second, using a self-signed certificate allows man-in-the-middle attacks. So, someone can steal the user's password and he probably won't even notice it. The user doesn't know the difference between the alert that pops up when the client receives your self-signed certificat and the pop up that shows when the attackers self-signed certificate is used.
My advice: Don't use self-signed certificates. When an attack happens it's bad for you and your customers.
When you use an SSL connection to encrypt a login dialogue with a password the server sends the client a public key (in the form of a certificate), and the client generates a one-off session key, encrypts it using the server's public key, and sends it to the server. The server can then decrypt the session key because it has the private key.
The user then encrypts his password using the session key and sends that to the server, which can decrypt it because it knows the session key.
Now, without PKI if an attacker wanted to learn your password he could spoof the server. He'd send you his public key and you'd generate a session key, etc., in the usual way and send him your password which he would be able to decrypt because you'd be using his key without knowing whether you can trust it.
PKI protects you against this kind of attack by requiring that public keys are distributed as certificates. If you trust the CA that signed the certificate you can tell that the public key really does belong to the server and that it's safe to use it to encrypt your password. If you don't use a certificate -- or if you use an untrusted certificate -- you generally have no idea who you are sending your password to.
You don't give enough information about your own particular use case to say for certain whether you can use a self-signed certificate ... For example: It may be that you have one fixed certificate that is distributed in advance by some trusted channel and that you can check that the correct certificate is being used when you begin your SSL conversation. If that's the case then your client already knows that it has the correct public key and doesn't need to be able to check a signature. In general, though, you need a proper certificate signed by a trusted CA or else you have no security.
That's the entire point of trusted signing authorities - anything signed by someone else is supposed to give a security alert. So, no, there's no useful way to override this (unless you have control over the client computers - e.g. a self-signed certificate used for company-internal sites, when you can add your own CA into the clients' list), either for web browsers or anything else.
With a self-signed certificate, how can a user know whether the certificate is yours or an attacker's? He can't.
If you completely control both ends of the process (server and client), you can of course instruct the client to always trust "certificate from Eugene with a fingerprint of A01AABB546AC", for example, but then you need to build your own certificate infrastructure (expiration/revocation).
You will add no theoretical security by using a self-signed certificate, because of the possibility of man in the middle. The counterparts (your client and your server) in this communication will have no additional information about who is talking or listening, whereas the point of this kind of encryption is to make sure that there are only two participants in the communication and that the identity of at least one of them is known.
In your case, the password will not be transferred to you securely, because you don't know if it has passed through a third party on the way. Likewise, the user won't know who he sends the password to.
In practice, a man in the middle attack will be a bit of work to set up, and maybe that obstacle is some kind of security, but contrast that to the annoyance of forcing your users to accept a security warning with unclear consequences, and indeed the risk of "false sense of security".
There are companies that offer free certificates with the lowest form of validation (they will only check that you "own" the e-mail address hostmaster#domain). That way you won't have to do with the warning, either.
Unless there is a way for you to package your certificate or its fingerprint with the app, as Piskvor said.
Moved to answer - for this type of thing you should be fine. The only thing the users won't get is a way to confirm the trust level of the cert (like you could do with a signed cert in a browser for example) but as per your comment to #Piskvor that doesn't sound like an issue: you aren't using it for that.

How does SSL actually work?

Whenever I see it being talked about, it sounds like one simply 'turns on' SSL and then all requests/responses to/from an online server are magically secure.
Is that right? Is SSL just about code - can I write two apps and make them communicate via SSL, or do you have to somehow register/certificate them externally?
Secure web pages are requested on port 443 instead of the normal port 80. The SSL protocol (plenty complicated in and of itself) is responsible for securing communication, and using the certificate information on both the SERVER and the BROWSER to authenticate the server as being who they say they are.
Generating an SSL certificate is easy. Generating one that is based on the information embedded in 99% of web browsers costs money. But the technical aspects are not different.
You see, there are organizations (Verisign, Globalsign, etc...) that have had their certificate authority information INCLUDED with browsers for many years. That way, when you visit a site that has a certificate that they produced (signed), your browser says:
"well, if Verisign trusts XYZ.com, and I trust Verisign, then I trust XYZ.com"
The process is easy:
Go to a competent SSL vendor, such as GlobalSign. Create a KEY and Certificate Request on the webserver. Use them (and your credit card) to buy a certificate. Install it on the server. Point the web-browser to HTTPS (port 443). The rest is done for you.
SSL is a protocol for encrypted communications over a TCP connection (or some other reliable scheme). The encryption uses public key encryption using X.509 certificates. SSL handles both privacy and trust. These are related: if you don't trust the server, you don't believe that the server hasn't handed out its private key to everyone in North America.
Thus, the client has to trust the server's certificate. For public sites, this is arranged via a hierarchy of certificate authorities, with the root authorities trusted, automatically, by browsers and things like the JRE's socket implementation.
Anyone can generate a self-signed certificate for a server, but then the client has to be manually configured to trust it.
SSL is not, in itself, a magic bullet that makes everything secure. Security has no such things.
SSL is, however, an already-designed, ready-to-use system for solving a common problem: secure stream communication over a network connection.
There are two things you need to do to secure your application with SSL:
Modify the application's code to use SSL.
Determine the certificate trust model (and deploy and configure the application respectively).
Other answers and documentation provide better answers to how to do each of these things than I could provide.
I'll throw caution to the wind and attempt to condense an enormous subject.
SSL attempts to solve two problems:
1) Authentication and hence trust i.e can the client trust the server and vice versa
2) Communication without eavesdropping
1) Is handled by means of an intermediary i.e a trusted 3rd party - these are called 'Root Certificate Authorities' ( or Root CAs ) examples include Verisign, RSA etc
If a company wants to authenticate users and more importantly if a user wants to authenticate the company's website it's connecting to i.e your bank then the Root CA issues the company a certificate which effectively says 'I the trusted Root CA verify that I trust that Company X are who they say they are and am issuing a certificate accordingly'. So you get a chain of trust i.e I trust the certificate from ACME Co because Root CA Verisign created and issued it.
2) Once the two parties have authenticated then the certificate ( typically X590 ) is used to form a secure connection using public/private key encryption.
Hopelessly simple and incomplete but hope that gives a rough idea
Yes and no. You should self-sign a certificate and test the site with SSL internally before deploying it with SSL, first of all. To make the public site secure under SSL, you will need to purchase a certificate from one of any number of certificate providers. Then you will have a certificate signed by a trusted third party, tied to your domain name, so that users' browsers won't complain that the certificate is invalid, etc. Turning SSL on is pretty much just flipping a switch, otherwise.
For the most part you need to buy and register a certificate externally.
You need to have your server certificate signed by a Certificate Authority (CA), for which they will charge you. The client needs to trust that CA and have a copy of the relevant CA public key. The client can then check that you are who you claim to be (including domain name (from DNS) and display name for https).
This is a good tutorial on how to create self signed certificates for Apache.
If you want to know how SSL works on either the Server or the Client, then I suggest Googling it. As you suspected, it is a ridiculesly complex procedure, with lots of communication between the client and server, a lot of very peculiar math, and tons of processing. There is also a lot of theory involved, several protocols and many different algorithms and encryption standards. It's quite incredible how changing http:// to https:// is so simple to the user, but results in so much work for both sides, and is so secure. To really understand it you need to take a security course (multiple courses to fully understand it), as the entire history of encryption goes into making your login to Gmail secure.
Turning on TLS (colloquially "SSL") does not make your site magically secure. You may still be vulnerable to application-level vulnerabilities like stack overflows, SQL injection, XSS, and CSRF.
As other answers have explained, TLS only protects against a man in the middle. Traffic between a client and a properly-configured TLS server cannot be intercepted or modified, and the client can reliably confirm the identity of the server by validating the X.509 certificate. This prevents an attacker from impersonating your TLS server.
SSL actually does two things:
Encrypts the communication so that an observer seeing the data stream will not be able to read the conversation.
Guarantees that you are talking to who you think you are talking to.
It is only for #2 that you need to get official certificates. If you only care to encrypt the communication without setting up a trust relationship, you can use self-signed certificates or you can use an algorithm that does not require certificates (i.e. Diffie-Hellman).

Resources