I.T. Security and Linux Administration

Jun 29 2012   3:39PM GMT

Stripping out information from SSH keypairs

Eric Hansen Eric Hansen Profile: Eric Hansen

Long time no post, hah.  But this post is about something involving SSH and the glorious ssh-keygen (keypair generator).  This won’t be beneficial to a lot of people, but for me it has posed to be quite a wonderful asset to my scripts.

Idea Behind This

Why would anyone want to strip out data from a SSH key pair?  For me, it’s because it was garbage.  I wasn’t going to be using the key pair for what they were intended for, but instead of writing my own key generator and such, this was the easiest method.  If you want random data for some person (noise on the network, testing data collection, etc…), this could prove to be a time saver.

What It Does

It does two things:

  1. Removes identifying information from the private key  (it states the key type, algorithm used, etc…)
  2. Keeps only the public key

A typical private keey looks like this:

Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,EE03FBC573CD3AAB6F1DA1740C60AD4A

<key snipped for clarity reasons>

While a public key will look like this:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCygEhgh2bCzhrD57EHMjOHNvpSE4zTUNyHwezkQgjer+m2qojlKxKouTbACMPxL6Q+ddtLAaJprwe4uCBNy5hTc6AkMFLkZ5ZZYYkBYMyxUX2UWU3zMUm7VOO9CeCMAiWf42jCbWuCEPXpgKgvQTEDIwG0zHk/mH1/USiWImR2kzDv1Kjmi8OGoy7sr6fKi8gWJWOW7lzNhbwCc0HrDhHX+G7GpVJ6mSyC32bVtFLjKc9oek+KZresuD493Dm7+XNNf+xw5Y/WuLcByGeSfSs7NKpRZaxTN4pqfh0W97LENDYfcmILsvlRYgYLuYYoY1SlCtEz6q0HyfF4i8P8KWIh comment-stamp

The end result, however, will be where in the private key all you have is the key itself, and the public key will have everything between “ssh-rsa” and the comment-stamp.

How This Is Done

As I didn’t want to manually enter the information for ssh-keygen myself each time, I automated the process (and without using expect!).  At the end of this post will be the script in it’s entirety, but right now I’m going to break it into parts a little.

DATA=`dd status=noxfer if=/dev/urandom ibs=1 | head -c1024 > /tmp/key`

As I don’t want to use a generic or standard passphrase, I use random data from /dev/urandom.  The “status=noxfer” argument is there because I didn’t want to see how much work dd did, as it wouldn’t fail unless the user couldn’t read /dev/urandom.  It’s stored in a temp file because I didn’t feel like echo’ing it into the while block I used next.  If you’re curious why I didn’t just use of=/tmp/key that’s because I only wanted the first 1024 bytes, which could’ve been resolved by count=1024 in the dd command, but this was efficient enough for me (I won’t be running this every minute).

Now onto the while loop:

while IFS= read -r -n1 d
TMP=$(printf "%02x" \'$d)

if [ "$TMP" != "00" ]; then
done < "/tmp/key"

To sum up this entire block, we are converting each character into a hex value, and only storing those hex values that aren’t 00.  As dd returns a bunch of ASCII data we need to tell printf that the data is ASCII (which is what the \’ is for).  We then only append it to the passphrase (KEY) if we don’t have a null/0 hex value.  We do this for each character we read from /dev/urandom (/tmp/key).

ssh-keygen -o -q -t rsa -N “$KEY” -f `pwd`/$FILE

Pretty straight forward if you know your ssh-keygen switches.  -o automatically overwrites a keypair without prompting, -q makes it so ssh-keygen does not output anything (i.e.: the ASCII chart it shows at the end), -t rsa specifies the key to be RSA (instead of DES), -N “$KEY” says to use KEY as the passphrase (so we’re not prompted for it) and -f specifies the location of the keypair.  $FILE is passed as an argument (FILE=”$1″) in the script.

If all goes well, you’ll get an automated SSH keypair, but it’s not stripped down yet.

Now, the stripping of the private key is a little bit involved, but here it is:

FRESH=$(cat `pwd`/$FILE | tail -n +5 | head -n -1 | sed -e ‘:a;N;$!ba;s/\n//g’)

Basically this is taking the private key, skipping the first 5 lines (information and an empty line) and the last line (see the example above).  The sed command is there because I did not want newlines in the private key.

I want to take a moment to talk about the sed command, as I didn’t write it myself but I follow it pretty well now.  With sed, there’s no real way to strip out newlines (\n) as sed parses each line up to the end of it (\n, , etc… if you know programming).  So, what you need to do is tell sed to create a label (a) and join newlines together (N), and while you haven’t reach the end of the data ($!) repeat the process (ba [b = branch, a = the label to go to]).  Then, sense we will have all the newlines on one line, we can then strip them out by globally (g) replacing (s) \n with nothing.

trim, in this case, wouldn’t work as you can’t trim something into nothing.

FRESH=$(cat `pwd`/$FILE.pub | awk ‘{print $2}’)

This just simply takes the public key itself and stores it.

After each FRESH you need to store the data back in the file, so do echo -n “$FRESH” > `pwd`/$FILE (or $FILE.pub for the public key).  I used the -n to enforce no newlines be inserted as well.


While this was a long post, it was worth writing this script.  Without further waiting, here it is:




[ -z "$FILE" ] && echo "No file specified.  Exiting." && exit

DATA=`dd status=noxfer if=/dev/urandom ibs=1 | head -c1024 > /tmp/key`
while IFS= read -r -n1 d
  	TMP=$(printf "%02x" \'$d)

        if [ "$TMP" != "00" ]; then
done  `pwd`/$FILE

FRESH=$(cat `pwd`/$FILE.pub | awk '{print $2}')
echo -n "$FRESH" > `pwd`/$FILE.pub

 Comment on this Post

There was an error processing your information. Please try again later.
Thanks. We'll let you know when a new response is added.
Send me notifications when other members comment.

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to:

Share this item with your network: