peer to peer secure communication: any available solutions? - security

I checked similar posts but I think the problem here maybe slightly different.
The problem is to provide secure communication between two peers (e.g., A and B) who may not have, how to say, "strong coupling" before (like A has its public key saved on B, that kind of thing).
The trust is based on a common signalling server who does the initial authentication (e.g., XMPP). Suppose A and B both login to that server. How would they proceed with secure and direct communication? I guess relevant keywords, using the XMPP example, would be XMPP secure socks5 (so far, this topic is uncovered in doc). Thank you for your suggestion on how I could start to implement, preferably using available library with less amount of work.

One protocol to look at is Off the Record, which has been used with XMPP in quite a few projects. The challenge you will have is how the users authenticate to each other, in a way that resists man-in-the-middle attacks. OTR uses Diffie-Hellman to exchange an AES key for bulk encryption and SHA256-HMAC. Users can then authenticate each other using a shared secret (like a passphrase), or compare public key fingerprints out of band.
I don't know if it counts as "strong coupling", but the other approach is to use certificates signed by a trusted 3rd party. If A has a certificate signed by you, and B has a certificate signed by you, then A and B can communicate securely without needing eachothers keys a priori.

Related

Is it possible to authenticate without asymmetric primitives and without a server?

I know that using an asymmetric algorithm is a very easy way to authenticate peers on a serverless network. I have a project where the networked clients only have symmetrical primitives. They have less than 1Mbyte code space and less than 100DMips, so running RSA in software would take too long.
If there is a server, this is not a hard problem. The client asks for authentication, the server sends a random number, the client does a HASH with secret (shared) key, and passes the result back to the server. Only a client with the secret would produce the answer the server is looking for, so the server is satisfied this is an authenticated client.
Here is the problem: what if all the devices on the network are peers, with none of them trusted more than others? Is it even possible to talk about general network-wide authentication without public key cryptography?
IF I could use RSA, then each node would have all the public keys of all the other nodes. Problem solved.
The only thing I can think of so far is to have each node store a public hash of each nodes private key. Then a series of secure transformations (http://en.wikipedia.org/wiki/Secure_multi-party_computation) are done to the hash in such a way that the other client can recover the transformations only if the hashed key belongs to them. Returning the transformations (without the secret) proves the node really is the one that owns that hash. Has anyone seen papers about this?
I suspect this is even more computationally expensive than just using RSA, but it is an interesting problem.
I have looked for other articles about this, but have not found much:
Authenticate without using a server
In addition to recommending not doing client-side authentication, this article suggests to make it good enough. That is not enough for me. I want something this is provably secure, like RSA, just without asymmetric components.
Here is the same problem: Decentralised user authentication -- possible?
but the answer is to use public-key authentication.
I just found a possible answer-- pre-shared keys:
http://en.wikipedia.org/wiki/TLS-PSK
I am afraid this means that one compromised device will compromise the entire network, but I have not dug in very far yet. More research to do.
Any other ideas you have come across?

Asynchronous vs. Synchronous Encryption Key and is SSL required for my app?

I'd like to secure the payload of a (local-notwork) TCP connection against attackers who snoop traffic. This payload only gets send in the direction from the client to the server.
As my application is not sensitive to client authenticity nor data integrity, i don't need signing/ceritificates.
Therefore the only feature of SSL i need would be its encryption/decryption aka confidentiality.
So i am wondering if a standalone encryption module was sufficient for me. While browsing SO, i frequently stumbled upon warnings about inventing its own security methods.
But now it interests me.
So, does a separate shared-key encryption algorithm give me the same protection as SSL, since i'm only interested in making the payload unreadable/unusable for an attacker. (Assert: i'm using the same encryption algorithm that SSL does)
And if so, does a (salted/IV) symmetric key encryption?
Is there an advantage to an asymmetric encryption, besides the fact, that the user does not need to remember a passprahse as he would need with a symmetric one?
EDIT: Just noted, that SSL uses a symmetric algorithm for the encryption part.
Just use SSL.
It was designed for exactly this purpose (to secure communications between a client an a server). Why do you want to re-invent the wheel to try to avoid using it?
This is a relevant post that you should really read: You are dangerously bad at cryptography...
I am completely agree with ircmaxell, you need to have SSL certificate installed on your website.
Now it is depending upon your requirement, which ssl certificate you should buy ! If you are looking for basic SSL product, you should check rapidssl which starts from $8/year.
If you are looking to secure multiple domains or looking for extended validations; there are different SSL available in market for these purposes.

Ciphertext on server

Are there any protocols which would allow 2 visitors to communicate securely through my website, without the possibility of me reading their messages?
Ask Google for End-to-End encryption like PGP/GPG. For a client-side browser-based implementation you might want to check out GPG encryption in JavaScript.
I just googled it and cannot tell if its really secure (not sending your private key to anyone). I just want to give you a point to start with.
EDIT: Looks like it does send the clients private key to your server to perform a server-based encryption. This is not what you want. But I am sure that a JavaScript implementation of GPG is possible even though I don't know if somebody has done it yet.
Yes; for example, this is what would happen if your server was a link in a communication protected by SSL/TLS.
The participants use a public-key encryption scheme to agree upon a secret, symmetric key; that is then used to encrypt their communication.
It's also possible for the participants to simply encrypt their messages with the public key of the intended receiver. That way, only the intended receiver can decrypt the message. This is not a very advanced scheme and probably vulnerable. (Among others, if an eavesdropper can guess exactly what is sent, he can encrypt that message with the intended recipient's public key and see if the result matches with what is being sent).
There is a lot of literature available on cryptographic protocols; for starters, here's a Wikipedia article on Key Agreement Protocols.
If we're talking about not possible then the second part to S.L. Barth's answer will achieve this with the exception that the key exchange must be done by some other means. This can be the phone or email or even another website but if it's done via your website then it's open to a man-in-the-middle attack. You can tell your users to do this, you just can't actually help them do it.
There is probably a javascript library somewhere that will implement GPG encryption so that all you have to do is make sure that every message is encrypted in the browser before it's sent to your web server. You can store the messages as long as you like, they're encrypted. Only the user with the correct private key will be able to decrypt it.
SSL and TLS as they are used by websites everywhere are vulnerable to man-in-the-middle attacks. The reason we don't hear much about these sorts of attacks is that most of the people in the middle are trustworthy so the attacks simply don't happen. The recent revoking of the CA certificates of DigiNotar and others was precisely because the Iranian Government were caught acting as a man-in-the-middle and decrypting their own citizen's SSL traffic.
If you're happy with preventing casual snooping by curious sysadmins, the key exchange can be done through your website as well.
One more thing: Security is hard.
Even if you do this with well-known encryption techniques, the chances of there being a flaw in the implementation will be very close to 1. This doesn't mean that those curious sysadmins will be able to accidentally read messages but it does mean that a determined and skilled adversary will be able to find a way in. As soon as you can afford it you should hire an expert to redesign or at the very least examine your protocol and implementation.
In general, such a secure link between your users without you being able to read and/or modify their messages is only possible if they have some way of identifying each other (or at least in one direction).
This might be a shared secret (like a passphrase) or a public key known to one (or certified by a CA known to one), where the other one has the corresponding private key.
On this one can build a secure protocol (using a key exchange and then symmetric encryption with MACs in both directions), like TLS does. (Another way, used often for instant messaging, is OTR, the Off-the-Record messaging protocol.)
Without a way to identify the other end point, you end up with a way of allowing man-in-the-middle attacks. SSL/TLS without certificates, or with certificates where the man-in-the-middle knows the corresponding private key, is insecure, as is every other similar encryption scheme.
Another issue is that you said visitors of my website. This looks like you would implement client-side cryptography in JavaScript, delivered from your website. Don't do this ... if the visitors do not trust you not to read their data, they also should not trust you to feed them non-malicious JavaScript, which might implement something else than you are claiming it does, again allowing a MITM, or even directly sending a copy of the data to you.
More details about this are discussed in Javascript Cryptography Considered Harmful (from a slightly different perspective).

Backwards HTTPS; User communicates with previously generated private key

I am looking for something like https, but backwards. The user generates their own private key (in advance) and then (only later) provides the web application with the associated public key. This part of the exchange should (if necessary) occur out-of-band. Communication is then encrypted/decrypted with these keys.
I've thought of some strange JavaScript approaches to implement this (From the client perspective: form submissions are encrypted on their way out while (on ajax response) web content is decrypted. I recognize this is horrible, but you can't deny that it would be a fun hack. However, I wondered if there was already something out there... something commonly implemented in browsers and web/application servers.
Primarily this is to address compromised security when (unknowingly) communicating through a rogue access point that may be intercepting https connections and issuing its own certificates. Recently (in my own network) I recreated this and (with due horror) soon saw my gmail password in plain text! I have a web application going that only I and a few others use, but where security (from a learning stand point) needs to be top notch.
I should add, the solution does not need to be practical
Also, if there is something intrinsically wrong with my thought process, I would greatly appreciate it if someone set me on the right track or directed me to the proper literature. Science is not about finding better answers; science is about forming better questions.
Thank you for your time,
O∴D
This is already done. They're called TLS client certificates. SSL doesn't have to be one-way; it can be two-party mutual authentication.
What you do is have the client generate a private key. The client then sends a CSR (Certificate Signing Request) to the server, who signs the public key therein and returns it to the client. The private key is never sent over the network. If the AP intercepts and modifies the key, the client will know.
However, this does not stop a rogue AP from requesting a certificate on behalf of a client. You need an out-of-band channel to verify identity. There is no way to stop a man in the middle from impersonating a client without some way to get around that MITM.
If a rogue access point can sniff packets, it can also change packets (an ‘active’ man-in-the-middle attack). So any security measure a client-side script could possibly provide would be easily circumvented by nobbling the script itself on the way to the client.
HTTPS—and the unauthorised-certificate warning you get when a MitM is trying to fool you—is as good as it gets.
SSL and there for HTTPS allows for client certificates. on the server side you can use these environment variables to verify a certificate. If you only have 1 server and a bunch of clients then a full PKI isn't necessary. Instead you can have a list of valid client certificates in the database. Here is more info on the topic.
Implementing anything like this in JavaScript is a bad idea.
I don't see, why you are using assymetric encryption here. For one, it is slow, and secondly, it is vulnerable to man in the middle anyhow.
Usually, you use an asymmetric encryption to have a relatively secure session negotiation, including an exchange of keys for a symmetric encryption, valid for the session.
Since you use a secure channel for the negociation, I don't really understand why you even send around public keys, which themselves are only valid for one session.
Asymmetric encryption makes sense, if you have shared secret, that allows verifying a public key. Having this shared secret is signifficantly easier, if you don't change the key for every session, and if the key is generated in a central place (i.e. the server and not for all clients).
Also, as the rook already pointed out, JavaScript is a bad idea. You have to write everything from scratch, starting with basic arithmetic operations, since Number won't get you very far, if you want to work with keys in an order of magnitude, that provides reasonable security.
greetz
back2dos

SSL authentication by comparing certificate fingerprint?

Question for all the SSL experts out there:
We have an embedded device with a little web server on it, and we can install our own SSL self-signed certificates on it. The client is written in .NET (but that doesn't matter so much).
How can I authenticate the device in .NET? Is it enough to compare the fingerprint of the certificate against a known entry in the database?
My understanding is that the fingerprint is a hash of the whole certificate, including the public key. A device faking to be my device could of course send the same public certificate, but it couldn't know the private key, right?
Or do I have to build up my own chain of trust, create my own CA root certificate, sign the web server certificate and install that on the client?
What you propose is in principle ok. It is for example used during key signing parties. Here the participants usually just exchange their name and fingerprints of their public keys and make sure that the person at the party really is who he/she claims. Just verifying fingerprints is much easier than to verify a long public key.
Another example is the so called self certifying file system. Here again only hashes of public keys get exchanged over a secure channel. (I.e. these hashes are embedded in URLs.) In this scheme the public keys don't have to be sent securely. The receiver only has to check that the hash of the public keys matche the hashes embedded in the URLs. Of course the receiver also has to make sure that these URLs come from a trusted source.
This scheme and what you propose are simpler than using a CA. But there is a disadvantage. You have to make sure that your database with hashes is authentic. If your database is large then this will likeley be difficult. If you use CAs then you only have to ensure that the root keys are authentic. This usually simplifies the key management significantly and is of course one reason, why CA based schemes are more popular than e.g. the self certifying file system mentioned above.
In the same way you wouldn't and shouldn't consider two objects to be equal just because their hash codes matched, you shouldn't consider a certificate to be authentic just because its fingerprint appears in a list of "known certificate fingerprints".
Collisions are a fact of life with hash algorithms, even good ones, and you should guard against the possibility that a motivated attacker could craft a rogue certificate with a matching fingerprint hash. The only way to guard against that is to check the validity of the certificate itself, i.e. check the chain of trust as you're implying in your last statement.
Short:
Well in theory you then do exactly what a Certificate Authority does for you. So it should be fine.
Longer:
When a Certificate Authority signs your public-key/certificate/certificate request it doesn't sign the whole certificate data. But just the calculated hash value of the whole certificate data.
This keeps the signature small.
When you don't want to establish your own CA or use a commercial/free one -
by comparing the fingerprint with the one you trust you'll gain the second most trustworthy configuration. The most trustworthy solution would be by comparing the whole certificate, because also protects you from hash collision attacks.
As the other guys here stated you should make sure to use a secure/safe hashing algorithm. SHA-1 is no longer secure.
more detailed informations to this topic:
https://security.stackexchange.com/questions/6737
https://security.stackexchange.com/questions/14330

Resources