SSH Communication Using Public and Private Keys - security

I am trying to understand how SSH authorization method work because I am trying to setup an git server using gitolite.
As far as I know gitolite will use the ssh to authorize users and give access to them to a specific repository with personal write and read permissions. But I am confused about how the authorization will work.
I've watched some videos in YouTube and they use some analogy with colors to explain. If I understand right, for two persons that are going to communicate between each other in a secret way, they need a secret and public key.
The two persons know each other public keys, and to communicate between each other they agree to use one public key. To establish a connection they encrypt they private key using the same public key and send the result to each other. When they receive the result they add the private key to that message and like magic they got the same message.
But I don't think I understand this right because I can't see how the server will verify the the client. I know the server had to hold the public keys from the clients that will connect to him, but he also got a private key?
When the client tries to connect to a server, he sends his private key encrypted with his public key, and the server encrypt his private key using the client public key and send to the client?
How the server check if the user is really him? I also read that to decrypt the information encrypted with a public key, only the person that holds the private key can decrypt the message. So how the server can decrypt the message send by the client if he don't have the client private key?
If someone could explain me how the authentication, authorization, and exchange of information work using this public and private keys I would be very happy.

SSH works roughly like the following. Note that this is merely a high level explanation:
Each party has two keys: a public key and a private key. The public/private keys are related mathematically, such that they are functionally inverse. Thus an operation performed by one can only be undone exactly by the other. It is complex, but think of it like calculating x^nnn versus the nnnth root of x. The former is easy but the latter is difficult, making it computationally unfeasible to guess with enough accuracy to undo the operation. This gives us some desirable attributes that allow SSH to do the following with them:
The client connects to the server. The server proves its identity by presenting a certificate signed with its private key. The client uses the server's public key to decrypt the certificate and knows that only the client could have encrypted it since it requires the private key. The server then does the same with a certificate presented by the client. Identification can only be performed with 100% assurance using a trusted third party to manage the public keys. Without the third party only identity changes can be detected.
Now that identities are verified, the server generates a symmetric secret key, encrypts it with the client's public key, and send it to the client (who is the only one that can decrypt the message since it requires the private key). From this point on, both the client and server have the symmetric secret key, and all communication is encrypted with this key. This is done for performance reasons because symmetric encryption operations are roughly 100 times faster than asymmetric operations.
This is how SSL verifies identities, and encrypts the information. Note that more granular access control are provided by higher level applications (such as *nix file permissions), not SSL.

Explanation of this subject is a little bit excessive for Stackoverflow format.
Few days ago Coursera started a free course on Cryptography (part I) that explains exactly the matters you are interested in.
I welcome you to cryptography course to find the answers for your questions

Related

distribute private key with application?

I'm building an application and want it to securely transfer data to a server.
Thinking to use public/private keys for initial handshake to encrypt a key with which to encrypt subsequent data.
Is it reasonable to have the private key integrated in the executable which will be distributed out in the wild for anyone to reverse-engineer?
I also thought of using three-pass protocol, but read about some of its weaknesses and it probably won't work for me
I followed Martin's advice and posted to security exchange (https://security.stackexchange.com/questions/158650/distribute-private-key-with-application).
There I received an answer that I accepted, by user Serverfrog:
Generate the Private/Public Keypair on the client, encrypt this with a
password (maybe choose from the User itself).
The send the Public Key encrypted via Server Public Key to the Server
and you have your entire Public/Private Stack.

SSL Public private key logic

I am reading SSL security logic articles. I am confused a bit. Server has private key and server sends client public key. An encrypted data with public key only can be decrypted by private key.
1- Client side has not a private key. How does client solve the server data?
2- if public key sending over internet, somebody can Access the key who listened the network.
3- encrypt and decrypt should have an algorithm. Do all browsers knows that algorithm? if browser companies knows that encrypt algorithm, this is a security problem.
The public and private keys aren't used for data encryption in SSL. They are only used in the authentication phase. That's why the client doesn't need a private key, unless the server requires client authentication. The actual encryption is done via symmetric encryption using a negotiated session key.
There are resources on the Internet that state otherwise, notoriously the Linux Documentation Project page. They are wrong. The normative reference is RFC 2246.
Your remark about knowing the encryption algorithm is quite incorrect. First, the client has to know the algorithm to be able to encrypt and decrypt. Second, it was established many years ago that security-by-obscurity simply does not work. True cryptographic security comes from well-designed and well-tested algorithms, however well-known they may be, and key length.

What makes SSL secure?

I've been reading a few sites on the internet on how SSL works, but I don't understand how exactly it makes things secure. Probably because I don't understand completely how it works.
Let me begin with the core idea of SSL. It is used to encrypt HTTP connections, but for the client and the server to communicate with encrypted data, surely an encryption key needs to be shared. If someone is eavesdropping on your connection, wouldn't they just be able to grab this key and continue listening while decrypting the data? I can image this technique would work if we're talking about a long term connection, but HTTP requests are often completed within half a second.
Let's assume this is somehow taken care of. The other utilisation of SSL is to verify if a server is exactly who it says it is. What prevents a rogue server from faking a certificate signed by a root certificate provider? In none of the descriptions I've read, the browser actually contacted one of these authorities to verify the certificate with them. Let's assume the certificate is encrypted with a private key by the root certificate authority, how is the browser able to verify the data in this certificate without knowing the decryption key? Or is the decryption key different from the encryption key?
One solution to these problems I can imagine is if the certificate and key are only sent once and are stored along with the domain and IP address in your browser.
Thanks for explaining in advance.
First, some basic concepts about public key cryptography:
This relies on a pair of keys. One is the public key (which can be distributed); the other one is the private key, intended to be kept private.
You can encrypt data using the public key, which the private key can decrypt/decipher.
You can sign data using the private key, and this signature can be verified using the public key.
To make sure you're communicating with the right entity, you need to bind an identity to a key-pair. This is where certificates come in. A public key certificate is a signed document containing both the subject's identity (name) and the subject's public key.
For example, the certificate for www.google.com contains its public key and the name www.google.com. It has been signed using the private key of a Certification Authority (in this case, Thawte). In the X.509 terminology (the common standard for certificates used for HTTPS), the CA is the issuer of the certificate, and it puts its name in the certificate too, alongside the subject's name, the subject's public key (and other attributes). The issuers are meant to verify the identity of who they issue a certificate for.
The reason you don't necessarily see your browser fetching information from the CAs is that a number of commercial (or governmental) CA certificates are bundled with your browser or your OS. You trust them by default. This can be considered as a "leap of faith", but any trust mechanism needs this sort of starting point.
You may want to read more about the TLS handshake, but in short:
The client gets the server's public key by looking into its certificate.
The client encrypts a secret using this public key and sends it to the server. The details of this depend on the cipher suite (could be Diffie-Hellman based), but the result of this should be a list of shared encryption keys (using symmetric cryptography, not public key cryptography).
These shared keys are only known to the client and the server, and they're used for encryption/decryption.
For SSL/TLS to be secure, you need at least 3 points:
A suitable cipher suite, and a successful handshake.
Verifying that the client trust the server certificate (typically, via a known CA in the PKI model).
Verifying that the certificate belongs to the server the client intended to contact (hostname verification).
(This is the case for the vast majority of usages of SSL/TLS (in particular HTTPS), but it's also possible to use other mechanisms than X.509 certificates with TLS, for example OpenPGP certificate or Kerberos cipher suites. This is less common as far as I know.)
In order to encrypt a connection you have to agree to some shared secret. This can be done with diffie-hellman. To prevent man in the middle attacks, so you also need a certificate mechanism.
For encrypting or signing (certificates) you can use asynchronous keys. This means you have two different keys (public and private key) to encrypt/decrypt. Usually you encrypt your data with a public key, and someone can decrypt it with his private key. Signing is done with your private key, and someone else can check it with a public key.
So you see, faking a certificate is not that easy, since you don't have the private key from a root certificate provider.
surely an encryption key needs to be shared. If someone is eavesdropping on your connection, wouldn't they just be able to grab this key
No. The key is never transmitted. It is computed at both ends independently via a key-agreement algorithm.
What prevents a rogue server from faking a certificate signed by a root certificate provider?
The certificate is sent along with its digital signature which is made with the private key, and verified by the peer via the certificate's own public key. The server would need the private key of the server it is spoofing.
When using protocols such as Diffie-Hellman key exchange, the two parties to a communication each generate a random number, transform it in some way, and send the transformed version to the other party. The transformation is such that combining the first number with the transformed version of the second will yield the same result as combining the second number with the transformed version of the first. An adversary who only had the transformed numbers, however, would have no way of finding the un-transformed version of either, nor a way of computing what the result would be if the (unavailable) untransformed version of one number were combined with the (available) transformed version of the other.
Diffie-Hellman key exchange by itself would be sufficient to protect against all forms of passive attack or historical attacks (meaning if an attacker hadn't taken steps to intercept a communication before it took place, it cannot later be compromised except by performing some calculations which could not, with anything resembling today's technology, be computed in any remotely feasible time). The problem with it is that it cannot very well protect against the situation where an attacker (e.g. Z) can intercept all communications between the participants (e.g. X and Y) and substitute his own. In that scenario, X would establish a connection with Z--thinking him to by Y--which nobody but he and Z could decode. Z would then--pretending to be X--establish a connection with Y.
If X and Y have any pre-existing means of sharing information with each other in such a way that they can decode it much faster than Z, even if it's not terribly secure, this may suffice to prevent the above-described man-in-the-middle attack. All that needs to happen is for X and Y to ask each other something about the key they're using. If Z can recognize that question and substitute its own answer, it would be able to continue the ruse. On the other hand, if the question were asked in such a way that a legitimate party would be able to respond much more quickly than an imposter, Z might be stumped. As an example, if a voice-phone application displayed for each participant information about the negotiated key, and one party asked the other "read off digits 12 to 18 of your key, doing your best impression of Elmer Fudd" (selecting, on the spot, the digits to read and the voice to use) a legitimate participant would be able to respond immediately, but an attacker would need time to produce a phony recording of the person speaking as indicated).

How to generate a client ssh key at each connection?

For now, I think that the public key that is used on a client-side is reused several times (maybe as long as the config dosn't change I think). I assume we are using the password method.
This worries me. I would prefer my ssh client to automatically generate a RSA key on each connection (but the Client-side key MUST remain the same to ensure authenticity and
Is this possible ?
Thanks.
EDIT : Please see comment #3.
The public key in SSH is used for identifying the client.
The private key is used for proving that the user is not an imposter.
The server only knows the public key. If you change it for each connection, it's like changing your username for each connection. So the server knows the user "john", but then you say "I'm Joe". It doesn't matter whether you can prove that you're Joe, the server doesn't know you, so it won't let you in.
It's not like SSL where you use a signed certificate to prove who you are, so you can change the key whenever you want. Here the public key is part of your identity, so you have to use the same one for every connection.
What you are missing is that the public and private keys are cryptographically bound to one another. When the private key is generated, the corresponding public key is as well. Encrypt something with one key and it can only be decrypted with the other. Anyone with the public key can validate that a message can only have come from someone with the private key because of this cryptographic relationship.
When an SSH session starts up, each side uses this property to authenticate the other. During the handshake a secret (technically, it's called a 'nonce' and it's basically a random number) is encrypted with the recipient's public key and then signed with the sender's private key. When this is received, the recipient a) can validate the signature with the sender's public key; and b) is the only one who can possibly decrypt the message. This authenticates the exchange. If this handshake occurs in both directions, it is possible for both sides to validate each other. This is called mutual authentication.
So, it is not the value of the key that is important but rather the cryptographic principle binding the public and private keys. This process provides the ability to create a random session key and exchange it securely using the public/private key pairs and is the heart of how SSH (or SSL or TLS for that matter) fires up a session.
This means the answer to your question is that if SSH is set up for mutual authentication (i.e. you do not need to enter a password), your client's public key must be in the keystore of the server. Since you cannot change the public key without changing the private key it is necessary to reload the public key at the server each time a key change is made.
If you use password authentication, no client side RSA key is used. If you use public key authentication, the client side key obviously can't change every time as the server needs to know it already in order to authenticate you.
You seem to have deep misconceptions about the SSH protocol. I can only suggest to read RFC 4252 to clarify things.

Strength of RSA Encrypting an AES Key

I'm currently developing a system to transmit data between client and server, and was wondering what the strength of the encryption I planned to use was.
My thought was to have a private/public RSA key pair and hand out the public key to each client (leaving the private key solely on the server). Each client would then generate their own AES key and RSA encrypt it. They would then AES encrypt their data and send the encrypted data and encrypted AES key to the server. The server would then decrypt the AES key using the private key, and then decrypt the data using the AES key.
Are there any security flaws I am missing and/or is there a better way to do this?
This is almost exactly how SSL/TLS works (check out the handshake section). The only thing to make it stronger is to generate the AES key for each connection, rather than using the same key each time. You might also want to digitally sign messages that go back and forth to avoid man-in-the-middle and other spoofing attacks.
Generally speaking, creating a good cryptosystem is very difficult. When possible, you should always favor an existing (trusted) application to help out. In this case, you might consider sending your messages using HTTPS, rather than creating your own system.
You should give us more information about the language and platform you are using, so that we can give you specific recommendations about libraries that already exist and wich will handle the details for you. Using cryptographic primitives directly is not trivial and difficult to get exactly right, and with cryptography, you have to be "not exactly right" only once for your security to be broken.
To answer your question, it's generally a better idea to create a session secret (the AES key) through a Diffie-Hellman exchange, and each side use its private RSA key to sign its key-exchange data.
Otherwise, if the session secret is not established through a DH exchange, an adversary that gains access to the private RSA key (which has to be stored somewhere) could decrypt all traffic that was ever sent between the client and server.
If the secret is established through a DH exchange, then only the authentication part of the protocol would be exposed. Although an adversary in possession of the private RSA key would then not be able to read any previous communication, he still could either enter an authenticated dialog with the client/server or launch a man-in-the-middle attack (which may or may not be easily done, depending on the network).
One vulnerability would be if an attacker substituted their public key for the "real" public key. Then they would be able to intercept traffic as a "man-in-the-middle."
Protocols like S/MIME, PGP, and TLS use RSA encryption to transport keys just as you propose. However, the public keys they use are in certificates signed by trusted authorities.
The integrity of these trusted authorities must be carefully protected. For example, they might be burned into a tamper-proof hardware token, or a MAC might be computed over them using a password.
I'm not sure your approach will protect anything! You're going to keep the private key on the server and the public key will be distributed. If I get a hold of your public key, I'll be able to interact with your server at will. I think you should reverse the key ownership; each client will hold it's-own private key and the server will have a list of public keys (ala SSH). The server will have to add 'authorized' public keys and only to holders of the private keys will be able to connect.
Hope this helps.

Resources