Difference between pages "Zope HOWTO" and "OpenSSH Key Management, Part 1"

(Difference between pages)
m
 
 
Line 1: Line 1:
This page documents how to use Zope with Funtoo Experimental, which currently has good Zope support thanks to [[Progress Overlay Python]] integration.
+
{{Article
 +
|Subtitle=Understanding RSA/DSA Authentication
 +
|Summary=In this series, you'll learn how RSA and DSA authentication work, and see how to set up passwordless authentication the right way. In the first article of the series, Daniel Robbins focuses on introducing the RSA and DSA authentication protocols and showing you how to get them working over the network.
 +
|Author=Drobbins
 +
|Next in Series=OpenSSH Key Management, Part 2
 +
}}
 +
Many of us use the excellent OpenSSH (see Resources later in this article) as a secure, encrypted replacement for the venerable telnet and rsh commands. One of OpenSSH's more intriguing features is its ability to authenticate users using the RSA and DSA authentication protocols, which are based on a pair of complementary numerical keys. As one of its main appeals, RSA and DSA authentication promise the capability of establishing connections to remote systems without supplying a password. While this is appealing, new OpenSSH users often configure RSA/DSA the quick and dirty way, resulting in passwordless logins, but opening up a big security hole in the process.
  
== About Zope ==
+
=== What is RSA/DSA authentication? ===
  
Zope is an Open Source application server framework written in Python. It has an interesting history which you should familiarize yourself with before starting Zope development, as it contains several interesting twists and turns.
+
SSH, specifically OpenSSH (a completely free implementation of SSH), is an incredible tool. Like telnet or rsh, the ssh client can be used to log in to a remote machine. All that's required is for this remote machine to be running sshd, the ssh server process. However, unlike telnet, the ssh protocol is very secure. It uses special algorithms to encrypt the data stream, ensure data stream integrity and even perform authentication in a safe and secure way.
  
=== Zope History ===
+
However, while ssh is really great, there is a certain component of ssh functionality that is often ignored, dangerously misused, or simply misunderstood. This component is OpenSSH's RSA/DSA key authentication system, an alternative to the standard secure password authentication system that OpenSSH uses by default.
  
There are two versions of Zope, Zope 2 and Zope 3. One might assume that Zope 3 is the version that people should use for new software development projects by default, but this is not the case. Most Zope-based projects continue to use Zope 2. Zope 3 was an attempt to redesign Zope 2 from scratch, and is completely different from Zope 2, but it was not adopted by the community.
+
OpenSSH's RSA and DSA authentication protocols are based on a pair of specially generated cryptographic keys, called the private key and the public key. The advantage of using these key-based authentication systems is that in many cases, it's possible to establish secure connections without having to manually type in a password.
  
There is also something called [http://codespeak.net/z3/five/ Five] (named because it is "2 + 3") that backports many of the new features of Zope 3 into the Zope 2 framework. Several projects will use Zope 2 plus Five in order to use some of the newer features in Zope. Five was merged into mainline Zope 2 in early 2010, and first appeared in Zope 2.8.
+
While the key-based authentication protocols are relatively secure, problems arise when users take certain shortcuts in the name of convenience, without fully understanding their security implications. In this article, we'll take a good look at how to correctly use RSA and DSA authentication protocols without exposing ourselves to any unnecessary security risks. In my next article, I'll show you how to use ssh-agent to cache decrypted private keys, and introduce keychain, an ssh-agent front-end that offers a number of convenience advantages without sacrificing security. If you've always wanted to get the hang of the more advanced authentication features of OpenSSH, then read on.
  
You can learn more about the history of Zope 2, 3 and Five in the [http://svn.zope.org/Zope/trunk/src/Products/Five/README.txt?view=markup Five README].
+
=== How RSA/DSA keys work ===
  
To make things even more interesting, work on [http://docs.zope.org/zope2/releases/4.0/ Zope 4] is underway, and it will be based on 2.13 rather than 3.x. It includes a number of [http://docs.zope.org/zope2/releases/4.0/CHANGES.html#restructuring incompatible changes] with prior versions.
+
Here's a quick general overview of how RSA/DSA keys work. Let's start with a hypothetical scenario where we'd like to use RSA authentication to allow a local Linux workstation (named localbox) to open a remote shell on remotebox, a machine at our ISP. Right now, when we try to connect to remotebox using the ssh client, we get the following prompt:
  
{{Note}} This HOWTO targets Zope 2.13, which includes Five. It is typically the version you should be using for new Zope projects.
+
<console>
 +
$ ##i##ssh drobbins@remotebox
 +
drobbins@remotebox's password:
 +
</console>
  
=== Zope Resources ===
+
Here we see an example of the ssh default way of handling authentication. Namely, it asks for the password of the drobbins account on remotebox. If we type in our password for remotebox, ssh uses its secure password authentication protocol, transmitting our password over to remotebox for verification. However, unlike what telnet does, here our password is encrypted so that it can not be intercepted by anyone sniffing our data connection. Once remotebox authenticates our supplied password against its password database, if successful, we're allowed to log on and are greeted with a remotebox shell prompt. While the ssh default authentication method is quite secure, RSA and DSA authentication open up some new possibilities.
  
Now that you understand what version of Zope you should be targeting (2.13), we can point you towards the correct documentation :)
+
However, unlike the ssh secure password authentication, RSA authentication requires some initial configuration. We need to perform these initial configuration steps only once. After that, RSA authentication between localbox and remotebox will be totally painless. To set up RSA authentication, we first need to generate a pair of keys, one private and one public. These two keys have some very interesting properties. The public key can be used to encrypt a message, and only the holder of the private key can decrypt it. The public key can only be used for encryption, and the private key can only be used for decryption of a message encoded by the matching public key. The RSA (and DSA) authentication protocols use the special properties of key pairs to perform secure authentication, without needing to transmit any confidential information over the network.
  
; [http://docs.zope.org/zope2/zope2book/ The Zope 2 Book]: This book provides a general introduction to Zope concepts and ZMI. It is a good place to start, but doesn't provide a direct introduction to Zope development. It's recommended that you skim through this book to familiarize yourself with Zope. It generally does not assume much prior knowledge about Web development or Python.
+
To get RSA or DSA authentication working, we perform a single one-time configuration step. We copy our public key over to remotebox. The public key is called "public" for a reason. Since it can only be used to encrypt messages for us, we don't need to be too concerned about it falling into the wrong hands. Once our public key has been copied over to remotebox and placed in a special file (~/.ssh/authorized_keys) so that remotebox's sshd can locate it, we're ready to use RSA authentication to log onto remotebox.
; [http://docs.zope.org/zope2/zdgbook/ Zope Developer's Guide]: This guide will give you a better introduction to Zope development. It assumes you already know Python. Skip chapters 1 and 2 and start in [http://docs.zope.org/zope2/zdgbook/ComponentsAndInterfaces.html chapter 3], which covers components and interfaces. [http://docs.zope.org/zope2/zdgbook/Products.html Chapter 5] covers the creation of your first product.
+
; Five: We're not done yet. There is a bunch of stuff in Zope 2.13 that is not in the official documentation. Namely, the stuff in Five. Check out [http://codespeak.net/z3/five/manual.html The Five Manual].
+
; ZTK: [http://docs.zope.org/ztkpackages.html ZTK Documentation]
+
; ZCA: [http://www.muthukadan.net/docs/zca.html A Comprehensive Guide to Zope Component Architecture] offers a good introduction to the programming concepts of ZCA. We also have a new page on [[Zope Component Architecture]] which will help you to understand the big picture of ZCA and why it is useful. ZCML ("Z-camel") is a part of ZCA and  was introduced in Zope 3, so typically you will find ZCML documented within Zope 3 documentation and book.
+
; Content Components: Views and Viewlets: [http://docs.zope.org/zope.viewlet/index.html This tutorial on viewlets] also contains some viewlet-related ZCML examples near the end. The "Content Component way" of developing in Zope seems to be a Zope 3 thing and tied to ZCML. Chapter 13+ of Stephan Richter's ''Zope 3 Developer's Handbook'' (book) seems to cover this quite well. You will probably also want to check out Philipp Weitershausen's ''Web Component Development with Zope 3'' (book).
+
; [http://wiki.zope.org/zope2/Zope2Wiki Zope 2 Wiki]: Main wiki page for all things related to Zope 2.
+
; [http://docs.zope.org docs.zope.org]: This is the main site for Zope documentation.
+
  
== First Steps ==
+
To do this, we simply type ssh drobbins@remotebox at localbox's console, as we always have. However, this time, ssh lets remotebox's sshd know that it would like to use the RSA authentication protocol. What happens next is rather interesting. Remotebox's sshd generates a random number, and encrypts it using our public key that we copied over earlier. Then, it sends this encrypted random number back to the ssh running on localbox. In turn, our ssh uses our private key to decrypt this random number, and then sends it back to remotebox, saying in effect "See, I really do hold the matching private key; I was able to successfully decrypt your message!" Finally, sshd concludes that we should be allowed to log in, since we hold a matching private key. Thus, the fact that we hold a matching private key grants us access to remotebox.
  
First, you will need to emerge {{Package|net-zope/zope}}:
+
=== Two observations ===
  
<console>
+
There are two important observations about the RSA and DSA authentication. The first is that we really only need to generate one pair of keys. We can then copy our public key to the remote machines that we'd like to access and they will all happily authenticate against our single private key. In other words, we don't need a key pair for every system we'd like to access. Just one pair will suffice.
# ##i## emerge -av zope
+
</console>
+
  
Zope is now installed.
+
The other observation is that our private key should not fall into the wrong hands. The private key is the one thing that grants us access to our remote systems, and anyone that possesses our private key is granted exactly the same privileges that we are. Just as we wouldn't want strangers to have keys to our house, we should protect our private key from unauthorized use. In the world of bits and bytes, this means that no one should be able to read or copy our private key.
  
== Project Skeleton ==
+
Of course, the ssh developers are aware of the private keys' importance, and have built a few safeguards into ssh and ssh-keygen so that our private key is not abused. First, ssh is configured to print out a big warning message if our key has file permissions that would allow it to be read by anyone but us. Secondly, when we create our public/private key pair using ssh-keygen, ssh-keygen will ask us to enter a passphrase. If we do, our private key will be encrypted using this passphrase, so that even if it is stolen, it will be useless to anyone who doesn't happen to know the passphrase. Armed with that knowledge, let's take a look at how to configure ssh to use the RSA and DSA authentication protocols.
  
{{Note}} Zope should be run by a regular user account, not as the root user.
+
=== ssh-keygen up close ===
  
The first step in using Zope is to ensure that you are using a regular user account. Create a new directory called ''<tt>zope_test</tt>'':
+
The first step in setting up RSA authentication begins with generating a public/private key pair. RSA authentication is the original form of ssh key authentication, so RSA should work with any version of OpenSSH, although I recommend that you install the most recent version available, which was openssh-2.9_p2 at the time this article was written. Generate a pair of RSA keys as follows:
<console>
+
$##bl## cd
+
$##bl## mkdir zope_test
+
</console>
+
  
Now, enter the directory, and create an "instance", which is a set of files and directories that are used to contain a Zope project:
 
 
<console>
 
<console>
$##bl## cd zope_test
+
$ ##i##ssh-keygen -t rsa
$##bl## /usr/lib/zope-2.13/bin/mkzopeinstance
+
Generating public/private rsa1 key pair.
 +
Enter file in which to save the key (/home/drobbins/.ssh/id_rsa): ##i##(hit enter)
 +
Enter passphrase (empty for no passphrase): ##i##(enter a passphrase)
 +
Enter same passphrase again: ##i##(enter it again)
 +
Your identification has been saved in /home/drobbins/.ssh/id_rsa.
 +
Your public key has been saved in /home/drobbins/.ssh/id_rsa.pub.
 +
The key fingerprint is:
 +
a4:e7:f2:39:a7:eb:fd:f8:39:f1:f1:7b:fe:48:a1:09 drobbins@localbox
 
</console>
 
</console>
  
You will see the following output, and will be prompted to answer a few questions:
+
When ssh-keygen asks for a default location for the key, we hit enter to accept the default of /home/drobbins/.ssh/id_rsa. ssh-keygen will store the private key at the above path, and the public key will be stored right next to it, in a file called id_rsa.pub.
<console>
+
Please choose a directory in which you'd like to install
+
Zope "instance home" files such as database files, configuration
+
files, etc.
+
  
Directory: instance
+
Also note that ssh-keygen prompted us to enter a passphrase. When prompted, we entered a good passphrase (seven or more hard-to-predict characters). ssh-keygen then encrypted our private key (~/.ssh/id_rsa) using this passphrase so that our private key will be useless to anyone who does not know it.
Please choose a username and password for the initial user.
+
These will be the credentials you use to initially manage
+
your new Zope instance.
+
  
Username: admin
+
=== The quick compromise ===
Password: ****
+
 
Verify password: ****
+
When we specify a passphrase, it allows ssh-keygen to secure our private key against misuse, but it also creates a minor inconvenience. Now, every time we try to connect to our drobbins@remotebox account using ssh, ssh will prompt us to enter the passphrase so that it can decrypt our private key and use it for RSA authentication. Again, we won't be typing in our password for the drobbins account on remotebox, we'll be typing in the passphrase needed to locally decrypt our private key. Once our private key is decrypted, our ssh client will take care of the rest. While the mechanics of using our remote password and the RSA passphrase are completely different, in practice we're still prompted to type a "secret phrase" into ssh.
</console>
+
  
Now, we will start our Zope instance:
 
 
<console>
 
<console>
$##bl## cd instance
+
$ ##i##ssh drobbins@remotebox
$##bl## bin/runzope
+
Enter passphrase for key '/home/drobbins/.ssh/id_rsa': (enter passphrase)
</console>
+
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org
  
Now that Zope is running, you can visit ''<tt>localhost:8080</tt>'' in your Web browser. You will see a nice introductory page to Zope.
+
Welcome to remotebox!
  
If you now go to the ''<tt>localhost:8080/manage</tt>'' URL, you will be prompted to log in. Enter the username and password you specified. You are now logged in to the ZMI (Zope Management Interface.)
+
$
 +
</console>
  
You can stop your application by pressing Control-C. In the future, you can start and stop your Zope instance using the following commands:
+
Here's where people are often mislead into a quick compromise. A lot of the time, people will create unencrypted private keys just so that they don't need to type in a password. That way, they simply type in the ssh command, and they're immediately authenticated via RSA (or DSA) and logged in.
  
 
<console>
 
<console>
$##bl## zopectl start
+
$ ##i##ssh drobbins@remotebox
$##bl## zopectl stop
+
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org
</console>
+
  
{{Note}} ''<tt>zopectl start</tt>'' will cause your instance to run in the background rather than consuming a shell console.
+
Welcome to remotebox!
  
== First Project ==
+
$
 +
</console>
  
We will create a single very primitive Zope package, consisting of an Interface for a TODO class, and a TODO class.
+
However, while this is convenient, you shouldn't use this approach without fully understanding its security impact. With an unencrypted private key, if anyone ever hacks into localbox, they'll also get automatic access to remotebox and any other systems that have been configured with the public key.
  
Create the following files and directories relative to your project root:
+
I know what you're thinking. Passwordless authentication, despite being a bit risky does seem really appealing. I totally agree. But there is a better way! Stick with me, and I'll show you how to gain the benefits of passwordless authentication without compromising your private key security. I'll show you how to masterfully use ssh-agent (the thing that makes secure passwordless authentication possible in the first place) in my next article. Now, let's get ready to use ssh-agent by setting up RSA and DSA authentication. Here step-by-step directions.
  
* Create the directory <tt>lib/python/example</tt>.
+
=== RSA key pair generation ===
* Create the file <tt>lib/python/example/__init__.py</tt> by typing <tt>touch lib/python/example/__init__.py</tt>.
+
* Create these files:
+
  
=== <tt>etc/package-includes/example-configure.zcml</tt> ===
+
To set up RSA authentication, we'll need to perform the one-time step of generating a public/private key pair. We do this by typing:
 
+
This file registers the ''<tt>example</tt>'' directory you created in ''<tt>lib/python</tt>'' as a ''package'', so that it is seen by Zope:
+
  
 
<console>
 
<console>
<include package="example" />
+
$ ##i##ssh-keygen -t rsa
 
</console>
 
</console>
  
=== <tt>lib/python/example/interfaces.py</tt> ===
+
Accept the default key location when prompted (typically ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub for the public key), and provide ssh-keygen with a secure passphrase. Once ssh-keygen completes, you'll have a public key as well as a passphrase-encrypted private key.
  
The following file defines the ''<tt>ITODO</tt>'' interface, and also uses some Zope Schema functions to define what kind of data we expect to store in objects that implement ''<tt>ITODO</tt>'':
+
=== RSA public key install ===
  
<console>
+
Next, we'll need to configure remote systems running sshd to use our public RSA key for authentication. Typically, this is done by copying the public key to the remote system as follows:
from zope.interface import Interface
+
from zope.schema import List, Text, TextLine, Int
+
  
class ITODO(Interface):
+
<console>
    name = TextLine(title=u'Name', required=True)
+
$ ##i##scp ~/.ssh/id_rsa.pub drobbins@remotebox:
    todo = List(title=u"TODO Items", required=True, value_type=TextLine(title=u'TODO'))
+
    daysleft = Int(title=u'Days left to complete', required=True)
+
    description = Text(title=u'Description', required=True)
+
 
</console>
 
</console>
  
=== <tt>lib/python/example/TODO.py</tt> ===
+
Since RSA authentication isn't fully set up yet, we'll be prompted to enter our password on remotebox. Do so. Then, log in to remotebox and append the public key to the ~/.ssh/authorized_keys file like so:
  
Now, we define ''<tt>TODO</tt>'' to be a ''persistent'' object, meaning it can be stored in the ZODB. We specify that it implements our previously-defined ''<tt>ITODO</tt>'' interface, and provide reasonable defaults for all values when we create a new TODO object:
 
 
<console>
 
<console>
from persistent import Persistent
+
$ ##i##ssh drobbins@remotebox
from zope.interface import implements
+
drobbins@remotebox's password: ##i##(enter password)
from example.interfaces import ITODO
+
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org
  
class TODO(Persistent):
+
Welcome to remotebox!
    implements(ITODO)
+
 
    name = u''
+
$ ##i##cat id_rsa.pub >> ~/.ssh/authorized_keys
    todo = []
+
$ ##i##exit
    daysleft = 0
+
    description = u''
+
 
</console>
 
</console>
  
=== <tt>lib/python/example/configure.zcml</tt> ===
+
Now, with RSA authentication configured, we should be prompted to enter our RSA passphrase (rather than our password) when we try to connect to remotebox using ssh.
  
Create an empty ''<tt>configure.zcml</tt>'' configuration file:
 
 
<console>
 
<console>
<configure xmlns="http://namespaces.zope.org/zope"
+
$ ssh drobbins@remotebox
    xmlns:five="http://namespaces.zope.org/five"
+
Enter passphrase for key '/home/drobbins/.ssh/id_rsa':
    xmlns:browser="http://namespaces.zope.org/browser">
+
</configure>
+
 
</console>
 
</console>
 +
 +
Hurray, RSA authentication configuration complete! If you weren't prompted for a passphrase, here are a few things to try. First, try logging in by typing ssh -1 drobbins@remotebox. This will tell ssh to only use version 1 of the ssh protocol, and may be required if for some reason the remote system is defaulting to DSA authentication. If that doesn't work, make sure that you don't have a line that reads RSAAuthentication no in your /etc/ssh/ssh_config. If you do, comment it out by pre-pending it with a "#". Otherwise, try contacting the remotebox system administrator and verifying that they have enabled RSA authentication on their end and have the appropriate settings in /etc/ssh/sshd_config.
  
== Debug Mode ==
+
=== DSA key generation ===
  
We can test our first project by entering debug mode:
+
While RSA keys are used by version 1 of the ssh protocol, DSA keys are used for protocol level 2, an updated version of the ssh protocol. Any modern version of OpenSSH should be able to use both RSA and DSA keys. Generating DSA keys using OpenSSH's ssh-keygen can be done similarly to RSA in the following manner:
<console>
+
$##bl## bin/zopectl debug
+
Starting debugger (the name "app" is bound to the top-level Zope object)
+
</console>
+
  
Now, let's try creating a new TODO object and writing it out to a ZODB database:
 
 
<console>
 
<console>
>>> from ZODB import FileStorage, DB
+
$ ##i##ssh-keygen -t dsa
>>> storage = FileStorage.FileStorage('mydatabase.fs')
+
>>> db = DB(storage)
+
>>> connection = db.open()
+
>>> import transaction
+
>>> root = connection.root()
+
>>> from example.TODO import TODO
+
>>> a = TODO
+
>>> a.name = u'My TODOs'
+
>>> a.TODOS = [ u'Do Laundry', u'Wash Dishes' ]
+
>>> a.daysleft = 1
+
>>> a.description = u'Things I need to do today.'
+
>>> root[u'today'] = a
+
>>> transaction.commit()
+
 
</console>
 
</console>
  
[[Category:HOWTO]]
+
Again, we'll be prompted for a passphrase. Enter a secure one. We'll also be prompted for a location to save our DSA keys. The default, normally ~/.ssh/id_dsa and ~/.ssh/id_dsa.pub, should be fine. After our one-time DSA key generation is complete, it's time to install our DSA public key to remote systems.
[[Category:Featured]]
+
 
 +
=== DSA public key install ===
 +
 
 +
Again, DSA public key installation is almost identical to RSA. For DSA, we'll want to copy our ~/.ssh/id_dsa.pub file to remotebox, and then append it to the ~/.ssh/authorized_keys2 on remotebox. Note that this file has a different name than the RSA authorized_keys file. Once configured, we should be able to log in to remotebox by typing in our DSA private key passphrase rather than typing in our actual remotebox password.
 +
 
 +
=== Next time ===
 +
 
 +
Right now, you should have RSA or DSA authentication working, but you still need to type in your passphrase for every new connection. In my next article, we'll see how to use ssh-agent, a really nice system that allows us to establish connections without supplying a password, but also allows us to keep our private keys encrypted on disk. I'll also introduce keychain, a very handy ssh-agent front-end that makes ssh-agent even more secure, convenient, and fun to use. Until then, check out the handy resources below to keep yourself on track.
 +
{{ArticleFooter}}

Revision as of 00:22, January 2, 2015

Understanding RSA/DSA Authentication

In this series, you'll learn how RSA and DSA authentication work, and see how to set up passwordless authentication the right way. In the first article of the series, Daniel Robbins focuses on introducing the RSA and DSA authentication protocols and showing you how to get them working over the network.


Next in series: OpenSSH Key Management, Part 2

Support Funtoo and help us grow! Donate $15 per month and get a free SSD-based Funtoo Virtual Container.
Looking for people interested in testing and documenting Docker support! Contact Daniel Robbins for more info.

Many of us use the excellent OpenSSH (see Resources later in this article) as a secure, encrypted replacement for the venerable telnet and rsh commands. One of OpenSSH's more intriguing features is its ability to authenticate users using the RSA and DSA authentication protocols, which are based on a pair of complementary numerical keys. As one of its main appeals, RSA and DSA authentication promise the capability of establishing connections to remote systems without supplying a password. While this is appealing, new OpenSSH users often configure RSA/DSA the quick and dirty way, resulting in passwordless logins, but opening up a big security hole in the process.

What is RSA/DSA authentication?

SSH, specifically OpenSSH (a completely free implementation of SSH), is an incredible tool. Like telnet or rsh, the ssh client can be used to log in to a remote machine. All that's required is for this remote machine to be running sshd, the ssh server process. However, unlike telnet, the ssh protocol is very secure. It uses special algorithms to encrypt the data stream, ensure data stream integrity and even perform authentication in a safe and secure way.

However, while ssh is really great, there is a certain component of ssh functionality that is often ignored, dangerously misused, or simply misunderstood. This component is OpenSSH's RSA/DSA key authentication system, an alternative to the standard secure password authentication system that OpenSSH uses by default.

OpenSSH's RSA and DSA authentication protocols are based on a pair of specially generated cryptographic keys, called the private key and the public key. The advantage of using these key-based authentication systems is that in many cases, it's possible to establish secure connections without having to manually type in a password.

While the key-based authentication protocols are relatively secure, problems arise when users take certain shortcuts in the name of convenience, without fully understanding their security implications. In this article, we'll take a good look at how to correctly use RSA and DSA authentication protocols without exposing ourselves to any unnecessary security risks. In my next article, I'll show you how to use ssh-agent to cache decrypted private keys, and introduce keychain, an ssh-agent front-end that offers a number of convenience advantages without sacrificing security. If you've always wanted to get the hang of the more advanced authentication features of OpenSSH, then read on.

How RSA/DSA keys work

Here's a quick general overview of how RSA/DSA keys work. Let's start with a hypothetical scenario where we'd like to use RSA authentication to allow a local Linux workstation (named localbox) to open a remote shell on remotebox, a machine at our ISP. Right now, when we try to connect to remotebox using the ssh client, we get the following prompt:

$ ssh drobbins@remotebox
drobbins@remotebox's password:

Here we see an example of the ssh default way of handling authentication. Namely, it asks for the password of the drobbins account on remotebox. If we type in our password for remotebox, ssh uses its secure password authentication protocol, transmitting our password over to remotebox for verification. However, unlike what telnet does, here our password is encrypted so that it can not be intercepted by anyone sniffing our data connection. Once remotebox authenticates our supplied password against its password database, if successful, we're allowed to log on and are greeted with a remotebox shell prompt. While the ssh default authentication method is quite secure, RSA and DSA authentication open up some new possibilities.

However, unlike the ssh secure password authentication, RSA authentication requires some initial configuration. We need to perform these initial configuration steps only once. After that, RSA authentication between localbox and remotebox will be totally painless. To set up RSA authentication, we first need to generate a pair of keys, one private and one public. These two keys have some very interesting properties. The public key can be used to encrypt a message, and only the holder of the private key can decrypt it. The public key can only be used for encryption, and the private key can only be used for decryption of a message encoded by the matching public key. The RSA (and DSA) authentication protocols use the special properties of key pairs to perform secure authentication, without needing to transmit any confidential information over the network.

To get RSA or DSA authentication working, we perform a single one-time configuration step. We copy our public key over to remotebox. The public key is called "public" for a reason. Since it can only be used to encrypt messages for us, we don't need to be too concerned about it falling into the wrong hands. Once our public key has been copied over to remotebox and placed in a special file (~/.ssh/authorized_keys) so that remotebox's sshd can locate it, we're ready to use RSA authentication to log onto remotebox.

To do this, we simply type ssh drobbins@remotebox at localbox's console, as we always have. However, this time, ssh lets remotebox's sshd know that it would like to use the RSA authentication protocol. What happens next is rather interesting. Remotebox's sshd generates a random number, and encrypts it using our public key that we copied over earlier. Then, it sends this encrypted random number back to the ssh running on localbox. In turn, our ssh uses our private key to decrypt this random number, and then sends it back to remotebox, saying in effect "See, I really do hold the matching private key; I was able to successfully decrypt your message!" Finally, sshd concludes that we should be allowed to log in, since we hold a matching private key. Thus, the fact that we hold a matching private key grants us access to remotebox.

Two observations

There are two important observations about the RSA and DSA authentication. The first is that we really only need to generate one pair of keys. We can then copy our public key to the remote machines that we'd like to access and they will all happily authenticate against our single private key. In other words, we don't need a key pair for every system we'd like to access. Just one pair will suffice.

The other observation is that our private key should not fall into the wrong hands. The private key is the one thing that grants us access to our remote systems, and anyone that possesses our private key is granted exactly the same privileges that we are. Just as we wouldn't want strangers to have keys to our house, we should protect our private key from unauthorized use. In the world of bits and bytes, this means that no one should be able to read or copy our private key.

Of course, the ssh developers are aware of the private keys' importance, and have built a few safeguards into ssh and ssh-keygen so that our private key is not abused. First, ssh is configured to print out a big warning message if our key has file permissions that would allow it to be read by anyone but us. Secondly, when we create our public/private key pair using ssh-keygen, ssh-keygen will ask us to enter a passphrase. If we do, our private key will be encrypted using this passphrase, so that even if it is stolen, it will be useless to anyone who doesn't happen to know the passphrase. Armed with that knowledge, let's take a look at how to configure ssh to use the RSA and DSA authentication protocols.

ssh-keygen up close

The first step in setting up RSA authentication begins with generating a public/private key pair. RSA authentication is the original form of ssh key authentication, so RSA should work with any version of OpenSSH, although I recommend that you install the most recent version available, which was openssh-2.9_p2 at the time this article was written. Generate a pair of RSA keys as follows:

$ ssh-keygen -t rsa
Generating public/private rsa1 key pair.
Enter file in which to save the key (/home/drobbins/.ssh/id_rsa): (hit enter)
Enter passphrase (empty for no passphrase): (enter a passphrase)
Enter same passphrase again: (enter it again)
Your identification has been saved in /home/drobbins/.ssh/id_rsa.
Your public key has been saved in /home/drobbins/.ssh/id_rsa.pub.
The key fingerprint is:
a4:e7:f2:39:a7:eb:fd:f8:39:f1:f1:7b:fe:48:a1:09 drobbins@localbox

When ssh-keygen asks for a default location for the key, we hit enter to accept the default of /home/drobbins/.ssh/id_rsa. ssh-keygen will store the private key at the above path, and the public key will be stored right next to it, in a file called id_rsa.pub.

Also note that ssh-keygen prompted us to enter a passphrase. When prompted, we entered a good passphrase (seven or more hard-to-predict characters). ssh-keygen then encrypted our private key (~/.ssh/id_rsa) using this passphrase so that our private key will be useless to anyone who does not know it.

The quick compromise

When we specify a passphrase, it allows ssh-keygen to secure our private key against misuse, but it also creates a minor inconvenience. Now, every time we try to connect to our drobbins@remotebox account using ssh, ssh will prompt us to enter the passphrase so that it can decrypt our private key and use it for RSA authentication. Again, we won't be typing in our password for the drobbins account on remotebox, we'll be typing in the passphrase needed to locally decrypt our private key. Once our private key is decrypted, our ssh client will take care of the rest. While the mechanics of using our remote password and the RSA passphrase are completely different, in practice we're still prompted to type a "secret phrase" into ssh.

$ ssh drobbins@remotebox
Enter passphrase for key '/home/drobbins/.ssh/id_rsa': (enter passphrase)
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org 

Welcome to remotebox!

$

Here's where people are often mislead into a quick compromise. A lot of the time, people will create unencrypted private keys just so that they don't need to type in a password. That way, they simply type in the ssh command, and they're immediately authenticated via RSA (or DSA) and logged in.

$ ssh drobbins@remotebox
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org 

Welcome to remotebox!

$

However, while this is convenient, you shouldn't use this approach without fully understanding its security impact. With an unencrypted private key, if anyone ever hacks into localbox, they'll also get automatic access to remotebox and any other systems that have been configured with the public key.

I know what you're thinking. Passwordless authentication, despite being a bit risky does seem really appealing. I totally agree. But there is a better way! Stick with me, and I'll show you how to gain the benefits of passwordless authentication without compromising your private key security. I'll show you how to masterfully use ssh-agent (the thing that makes secure passwordless authentication possible in the first place) in my next article. Now, let's get ready to use ssh-agent by setting up RSA and DSA authentication. Here step-by-step directions.

RSA key pair generation

To set up RSA authentication, we'll need to perform the one-time step of generating a public/private key pair. We do this by typing:

$ ssh-keygen -t rsa

Accept the default key location when prompted (typically ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub for the public key), and provide ssh-keygen with a secure passphrase. Once ssh-keygen completes, you'll have a public key as well as a passphrase-encrypted private key.

RSA public key install

Next, we'll need to configure remote systems running sshd to use our public RSA key for authentication. Typically, this is done by copying the public key to the remote system as follows:

$ scp ~/.ssh/id_rsa.pub drobbins@remotebox:

Since RSA authentication isn't fully set up yet, we'll be prompted to enter our password on remotebox. Do so. Then, log in to remotebox and append the public key to the ~/.ssh/authorized_keys file like so:

$ ssh drobbins@remotebox
drobbins@remotebox's password: (enter password)
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org 

Welcome to remotebox!

$ cat id_rsa.pub >> ~/.ssh/authorized_keys
$ exit

Now, with RSA authentication configured, we should be prompted to enter our RSA passphrase (rather than our password) when we try to connect to remotebox using ssh.

$ ssh drobbins@remotebox
Enter passphrase for key '/home/drobbins/.ssh/id_rsa':

Hurray, RSA authentication configuration complete! If you weren't prompted for a passphrase, here are a few things to try. First, try logging in by typing ssh -1 drobbins@remotebox. This will tell ssh to only use version 1 of the ssh protocol, and may be required if for some reason the remote system is defaulting to DSA authentication. If that doesn't work, make sure that you don't have a line that reads RSAAuthentication no in your /etc/ssh/ssh_config. If you do, comment it out by pre-pending it with a "#". Otherwise, try contacting the remotebox system administrator and verifying that they have enabled RSA authentication on their end and have the appropriate settings in /etc/ssh/sshd_config.

DSA key generation

While RSA keys are used by version 1 of the ssh protocol, DSA keys are used for protocol level 2, an updated version of the ssh protocol. Any modern version of OpenSSH should be able to use both RSA and DSA keys. Generating DSA keys using OpenSSH's ssh-keygen can be done similarly to RSA in the following manner:

$ ssh-keygen -t dsa

Again, we'll be prompted for a passphrase. Enter a secure one. We'll also be prompted for a location to save our DSA keys. The default, normally ~/.ssh/id_dsa and ~/.ssh/id_dsa.pub, should be fine. After our one-time DSA key generation is complete, it's time to install our DSA public key to remote systems.

DSA public key install

Again, DSA public key installation is almost identical to RSA. For DSA, we'll want to copy our ~/.ssh/id_dsa.pub file to remotebox, and then append it to the ~/.ssh/authorized_keys2 on remotebox. Note that this file has a different name than the RSA authorized_keys file. Once configured, we should be able to log in to remotebox by typing in our DSA private key passphrase rather than typing in our actual remotebox password.

Next time

Right now, you should have RSA or DSA authentication working, but you still need to type in your passphrase for every new connection. In my next article, we'll see how to use ssh-agent, a really nice system that allows us to establish connections without supplying a password, but also allows us to keep our private keys encrypted on disk. I'll also introduce keychain, a very handy ssh-agent front-end that makes ssh-agent even more secure, convenient, and fun to use. Until then, check out the handy resources below to keep yourself on track.

Next >>>

Read the next article in this series: OpenSSH Key Management, Part 2

Support Funtoo and help us grow! Donate $15 per month and get a free SSD-based Funtoo Virtual Container.
Looking for people interested in testing and documenting Docker support! Contact Daniel Robbins for more info.

About the Author

Daniel Robbins is best known as the creator of Gentoo Linux and author of many IBM developerWorks articles about Linux. Daniel currently serves as Benevolent Dictator for Life (BDFL) of Funtoo Linux. Funtoo Linux is a Gentoo-based distribution and continuation of Daniel's original Gentoo vision.

Got Funtoo?

Have you installed Funtoo Linux yet? Discover the power of a from-source meta-distribution optimized for your hardware! See our installation instructions and browse our CPU-optimized builds.

Funtoo News

Mgorny

New OpenGL management in Funtoo

Funtoo is switching to an improved system for managing multiple OpenGL providers (Mesa/Xorg, AMD and nVidia). The update may involve blockers and file collisions.
30 March 2015 by Mgorny
Drobbins

Subarch Profiles are coming...

Subarch profiles are on their way! Learn more here.
29 March 2015 by Drobbins
Drobbins

RSS/Atom Support

You can now follow this news feed at http://www.funtoo.org/news/atom.xml .
10 February 2015 by Drobbins
View More News...

More Articles

Browse all our Linux-related articles, below:

A

B

F

G

K

L

M

O

P

S

T

W

X

Z