Search My Blog

ruby (4) web (4) ruby on rails (3) security (3) GPG (2) OpenPGP (2) RFC (2) linux (2) rails (2) shell (2) sysadmin (2) Exchange (1) GIT. (1) IMAP (1) RCS (1) SSH (1) SVN (1) bundle (1) cURL (1) command line (1) crack (1) css (1) developer (1) email (1) fail (1) hack (1) http (1) mac (1) network (1) password (1) regular expression (1) script (1) subversion (1) terminal (1) textmate (1) tip (1) vim (1)

Wednesday, February 15, 2012

What is GnuPG and how to create your GPG primary key and subkeys



Daniel-san, must talk. Walk on road, hm? Walk left side, safe. Walk right side, safe. Walk middle, sooner or later, get squish just like grape. Here, karate, same thing. Either you karate do "yes", or karate do "no". You karate do "guess so", get squish just like grape. Understand?
- Mr Kesuke Miyagi


For GPG the same holds true. It's never a good idea to entrust your safety to a stranger.
If you are starting with GPG you may be frightened by the lack of a short, practical documentation about how to create your keys and how to best use them. Unfortunately GPG seems to be a niche topic for insider people, I've been very frustrated learning how do certain thing work.
So I'm writing a few number of posts that should help people with little or no knowledge about public key cryptography to gain confidence with the GNU Privacy Guard (GnuPG or GPG) implementation of the PKC paradigma. Current versions of PGP are interoperable with GnuPG and other OpenPGP-compliant systems. GnuPG is a part of the Free Software Foundation's GNU software project, and has received major funding from the German government.


What is Public Key Cryptography (PKC)?

As written in the The GNU Privacy Handbook by the The Free Software Foundation (FSF), Public-key ciphers are based on one-way trapdoor functions. A one-way function is a function that is easy to compute, but the inverse is hard to compute. For example, it is easy to multiply two prime numbers together to get a composite, but it is difficult to factor a composite into its prime components. A one-way trapdoor function is similar, but it has a trapdoor. That is, if some piece of information is known, it becomes easy to compute the inverse. For example, if you have a number made of two prime factors, then knowing one of the factors makes it easy to compute the second. Given a public-key cipher based on prime factorization, the public key contains a composite number made from two large prime factors, and the encryption algorithm uses that composite to encrypt the message. The algorithm to decrypt the message requires knowing the prime factors, so decryption is easy if you have the private key containing one of the factors but extremely difficult if you do not have it.


What is a "key" and what you can do with it?

In public key cryptography, as opposed to symmetic key cryptography, a “key” actually of two parts, you can think about them as the two very large prime numbers used in the one-way trapdoor function described above: a public key, and a secret (or private) key; for this reason it would be more appropriate to refer to a “key pair”.
More about the analogy between a key pair and the prime numbers can be found on the RSA working example on Wikipedia

With a key pair you can mainly do two sort of things on some data: sign & verify, or encrypt & decrypt:
- You use your secret key to digitally sign files, and others use your public key to verify the signature.
- Or, others use your public key to encrypt something, and you use the secret key to decrypt it.

One very special use of a key pair is to sign other people’s public key: doing so, you mean that you trust that key pair as belonging to someone you know in person. The more people sign your public key, the more trustable it is. A group of people that trust each other signing their keys is called a web of trust. A “web of trust” is the cryptography equivalent of “reputation”. This model is opposed to the centralized trust model of a public key infrastructure (PKI), which relies exclusively on a certificate authority (or a hierarchy of such).

As the word suggests, a secret key (and its backup) should be kept out of reach from any other person, whereas the public key should spread all over the world so that others have a mean to verify your authenticity and encrypt files for your eyes only.

Once your primary (master) key has been trusted by many people, properly used and mantained, it becomes one of the best proof of your online identity, so you should store it in a safe and possibly disconnected place.
And here’s where the subkeys come into play.


How to create my GPG key and subkeys

OpenPGP encourages use of multiple subkeys, which are like the normal key pairs, except that they are always listed along with their master key pair.
When you create your own key pair,

$ gpg -v --gen-key
gpg (GnuPG/MacGPG2) 2.0.17; Copyright (C) 2011 Free Software Foundation, Inc.

gpg: keyring `~/.gnupg/secring.gpg' created
gpg: keyring `~/.gnupg/pubring.gpg' created

ALGORITHM:
Please select what kind of key you want:
(1) RSA and RSA (default because it’s now the best choice)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1

KEYSIZE:
What keysize do you want? (2048) 4096

EXPIRATION:
Please specify how long the key should be valid.
0 = key does not expire
= key expires in n days
w = key expires in n weeks
m = key expires in n months
y = key expires in n years
Key is valid for? (0) 0

IDENTITY:
GnuPG needs to construct a user ID to identify your key.
Real name: Claudio Floreani
Email address: a.valid@email.com
Comment: Write here something that will help other people to recognize you

You need a Passphrase to protect your secret key.
gpg: writing public key to `~/.gnupg/pubring.gpg'
gpg: writing secret key to `~/.gnupg/secring.gpg'
gpg: ~/.gnupg/trustdb.gpg: trustdb created
gpg: using PGP trust model
gpg: key 889C36B7 marked as ultimately trusted
public and secret key created and signed.

pub 4096R/889C36B7 2010-10-01 (MASTER KEY, usage: SC, sign and certify)
Key fingerprint = 0ABE C1F7 D52A F468 A483 466A 0F6D 370E 889C 36B7
uid Claudio Floreani (some clues about me)
sub 4096R/E6F9976E 2010-10-01 (DEFAULT SUBKEY, usage: E, encryption)
GnuPG actually builds a signing-only key as the master key (the one marked with “pub” and flagged "Sign" and "Certify"), and creates an encryption subkey automatically (the one marked with “sub” and flagged “Encrypt”).


Revocation certificate: when you should build it and why you should use it?

After your keypair is created you should immediately generate a revocation certificate for the whole key using the command --gen-revoke (note: to revoke a subkey or a signature, use the  subcommands revkey or revsig from --edit-key):

$ gpg --gen-revoke 889C36B7 > revoc_cert/889C36B7_revoc_cert.asc
(this won’t alter your keyring)
You can then import that revocation certificate onto your keyring to revoke the key. Think about the revocation certificate as an insurance that lets you keep ultimate control over your key. Once you decided to get rid of your key you would like to share this revocation certificate, keeping in mind that a revoked public key:
  • can still be used to verify signatures made by you in the past
  • cannot be used to encrypt future messages to you
  • can be used to decrypt messages sent to you in the past (if you still do have access to the secret key)



GPG file types

You may have noticed that the certificate has an .asc extension. That’s because by default this command output a text file.

GnuPG uses two main file types:
- .ASC: ASCII Armored files (MIME: application/pgp-keys): a special text format that GPG (and PGP) use to convert binary data into ASCII text so that is especially suitable for use in email messages.
- .GPG: Binary files (MIME: application/x-pgp-keyring): By default most GPG operations produce this binary files that designed to be used directly by GPG (or PGP).

By default GPG creates its keyring under a hidden folder named .gnupg in the user's home (~/.gnupg), but you can override this specifying a GNUPGHOME environment variable:
$ export GNUPGHOME="/another/path/"
Under this folder, GPG creates these files at the first usage:
secring.gpg - Holds the secret keyring (can be viewed with gpg -k or gpg --list-keys)
pubring.gpg - Holds the public keyring (can be viewed with gpg -K or gpg --list-secret-keys)
trustdb.gpg - It's the trust database. (There is no need to backup this file, it is better to backup the ownertrust values: gpg –export-ownertrust)
random_seed - Is used to preserve the internal random pool
gpg.conf - Default configuration file
In the following post I will describe some basic GPG usage, and take a depth look at subkeys and their capabilities.


Friday, January 27, 2012

How to put any directory under SVN revision control using a self-contained repository

Okay, I've not found this elsewhere so I'm writing a post about how I did it.
The tipical SVN scenario is when you and other people are working on shared files by checking out any number of working copies from a repository,
$ svn checkout http://svn.collab.net/repos/svn/trunk /home/me/src/project4/working_copy3
modifying the files and then committing the changes and let the revision control system manage conflicts and merge the updates.
$ svn commit -m "Corrected number of cheese slices."
In this scenario the best place for the repository is in a dedicated and secured server, it doesn't make any sense to have the repository inside its working copy: you want to feel free to make any kind of disaster and even delete the whole directory because you know you can start all over again by checking out a fresh original copy.

But SVN is so simple and powerful that you can let it track any changes that happens on a directory on your own personal computer, for backup or security purposes (think about /etc) or to study what an application does to the the files; and sometimes it may be convenient to create the repository in the same directory that repository is controlling, so you can always backup and move the directory without worrying to break the relationship between the working copy and the repository.
In my case I had an encrypted volume that I mount and unmount in different computers and I wanted to track the changes on this volume even without a network connection, so it turned out that making a self-contained SVN system was the best choice.

There are some simple initial steps to do this, and once completed you can work on the directory as you do usually with any other working copy. Before proceeding just make sure to make a backup of anything you are touching.


Suppose "/pwd" is the directory you want to put under revision control, and start creating a SVN repository where you want (since it will be moved later, I'll place it under /tmp):
$ svnadmin create /tmp/repo/
then import /pwd in this repository and remove it if successfully imported:
$ svn import /pwd/ file:///tmp/repo/ -m '[/] Start tracking all changes within pwd' && rm -fr /pwd/
Now if you check it out you'll have just put /pwd under revision control:
$ svn checkout file:///tmp/repo/ /pwd/

...but wait! IT'S NOT THAT SIMPLE FOR "LIVE" DIRECTORIES!
If you are working on a "live" directory (such as /etc on a busy system), it's not very safe to simply import and delete it because some files may need to change before you check out. So on a "live" directory we'll do it slightly differently:
$ svnadmin create /tmp/repo/
$ svn import /pwd/ file:///tmp/repo/ -m '[/] Start tracking all changes within pwd'
we'll check out under another temporary path
$ svn checkout file:///tmp/repo/ /tmp/pwd/
and move just the SVN system folders into the "live directory":
$ find /tmp/pwd/ -type d -name ".svn" -exec mv -vi {} /pwd/ \;
NOTE: In a Mac OS environment, use 'ditto' instead of 'mv':
$ cd /tmp/pwd/
$ find . -d -type d -name ".svn" -exec ditto {} /pwd/{} \;
$ cd ~-
Now /pwd is effectively a working copy and you can update the files that changed in the meanwhile, and get rid off the other working copy /tmp/pwd:
$ rm -fr /tmp/pwd/

And here comes the part to move the repository inside the working copy:
Change to /pwd/ and update (only needed if it was a "live" directory)
$ cd /pwd/ && svn update
tell SVN to ignore the folder ".repo" where we will put the repository, and commit.
$ svn propset svn:ignore .repo .
$ svn commit -m '[/] svn propset svn:ignore .repo .'
At this point, instead of just moving the repository in "/pwd/.repo", we make a precautionary step to ensure that if we are working on a "live" directory no changes would be lost when we relocate the repository: first we symlink the repository,
$ ln -s /tmp/repo/ .repo
then we tell what is the new location of the SVN repository
$ svn switch --relocate file:///tmp/repo/ file:///pwd/.repo/
and only after making the switch we effectively move it replacing the symlink all at once
$ rm /pwd/.repo && mv -vf /tmp/repo/ /pwd/.repo/
Now you have a self-contained revision control of the current directory.



If you find this useful please leave a comment ;)

Monday, January 9, 2012

Monkeypatching the Ruby IMAP class to build a client for Exchange email servers not compliant with RFC standards

When trying to use Ruby Class Net::IMAP to automate some searching/arranging/deleting tasks for my office email I came across some Exchange responses that are not strictly compliant with the IMAP standard (currently 4rev1, described in RFC3501)

After loading the standard IMAP class
ruby-1.9.2-p290 :001 > require 'net/imap'
=> true

we can connect to the IMAP server by instantiating an Net::IMAP object that describes the type of connection used (IP address, TCP port and whether we should use SSL to encrypt the communication).
My company uses IMAP over SSL (port 993/tcp) with a 'PLAIN' authentication, so let's start with:
ruby-1.9.2-p290 :002 > imap= Net::IMAP.new( 'outlook.h3g.it', :port=>'imaps', :ssl=>true )
=> #<Net::IMAP:0x0000010109e118 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x0000010109e0c8>, @host="outlook.h3g.it", @port="imaps", @tag_prefix="RUBY", @tagno=0, @parser=#<Net::IMAP::ResponseParser:0x0000010109e028 @str="* OK IMAP4 019 Ready\r\n", @pos=22, @lex_state=:EXPR_BEG, @token=nil, @flag_symbols={}>, @sock=#<OpenSSL::SSL::SSLSocket:0x0000010109d678>, @usessl=true, @responses={}, @tagged_responses={}, @response_handlers=[], @tagged_response_arrival=#<MonitorMixin::ConditionVariable:0x0000010109bb70 @monitor=#<Net::IMAP:0x0000010109e118 ...>, @cond=#<ConditionVariable:0x0000010109bb48 @waiters=[], @waiters_mutex=#<Mutex:0x0000010109baf8>>>, @continuation_request_arrival=#<MonitorMixin::ConditionVariable:0x0000010109bad0 @monitor=#<Net::IMAP:0x0000010109e118 ...>, @cond=#<ConditionVariable:0x0000010109baa8 @waiters=[], @waiters_mutex=#<Mutex:0x0000010109ba58>>>, @idle_done_cond=nil, @logout_command_tag=nil, @debug_output_bol=true, @exception=nil, @greeting=#<struct Net::IMAP::UntaggedResponse name="OK", data=#<struct Net::IMAP::ResponseText code=nil, text="IMAP4 019 Ready">, raw_data="* OK IMAP4 019 Ready\r\n">, @client_thread=#<Thread:0x00000100892c80 run>, @receiver_thread=#<Thread:0x0000010109afb8 run>>

So far so good, but when I introduce myself to the server I receive an error:
ruby-1.9.2-p290 :003 > imap.authenticate( 'PLAIN', my_name, my_password )
Net::IMAP::ResponseParseError: unexpected token CRLF (expected SPACE)
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:3235:in `parse_error'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:3087:in `match'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:2058:in `continue_req'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:2045:in `response'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1973:in `parse'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1124:in `get_response'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1036:in `receive_responses'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1023:in `block in initialize'

It seems that our client is expecting a T_SPACE while server is sending T_CRLF. Interesting to say, Microsoft states that Exchange is "compatible with RFC3501" but also that "(AUTH=PLAIN not supported)" (http://technet.microsoft.com/en-us/library/ff848256.aspx). Why?? It seems to me that once again they are not able to understand a clear (A)BNF specification on a standard RFC:

RFC3501: INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1
9. Formal Syntax
response = *(continue-req / response-data) response-done
continue-req = "+" SP (resp-text / base64) CRLF
response-data = "*" SP (resp-cond-state / resp-cond-bye / mailbox-data / message-data / capability-data) CRLF
response-done = response-tagged / response-fatal
response-fatal = "*" SP resp-cond-bye CRLF ; Server closes connection immediately
response-tagged = tag SP resp-cond-state CRLF

RFC clearly says that a SP(ace) is needed after the "+" sign, as correctly defined in the 'continue_req' method:
require 'net/imap'
module Net
class IMAP
class ResponseParser
def continue_req
match(T_PLUS)
match(T_SPACE)
return ContinuationRequest.new(resp_text, @str)
end
end
end
end

however we can try to fix (but I should say 'break') it to suit the Exchange server's needs, deleting the 'match(T_SPACE)' statement:
require 'net/imap'
module Net
class IMAP
class ResponseParser
def continue_req
match(T_PLUS)
return ContinuationRequest.new(resp_text, @str)
end #def continue_req
end #class ResponseParser
end #class IMAP
end #module Net

And then try again:
ruby-1.9.2-p290 :004 > imap.authenticate( 'PLAIN', my_name, my_password )
=> #, raw_data="RUBY0001 OK AUTHENTICATE completed.\r\n">

And now it's ok.
But testing some other IMAP command we soon face another error:
ruby-1.9.2-p290 :005 > imap.noop
=> #, raw_data="RUBY0002 OK NOOP completed.\r\n">

ruby-1.9.2-p290 :006 > imap.status( 'INBOX', 'MESSAGES' )
Net::IMAP::ResponseParseError: unexpected token SPACE (expected CRLF)
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:3235:in `parse_error'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:3087:in `match'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:2051:in `response'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1973:in `parse'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1124:in `get_response'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1036:in `receive_responses'
from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/imap.rb:1023:in `block in initialize'

Exchange server (sometimes?) adds an extra space before CRLF (again violating the RFC command syntax listed above).
This time we need to change the response method:
require 'net/imap'
module Net
class IMAP
class ResponseParser
def response
token = lookahead
case token.symbol
when T_PLUS
result = continue_req
when T_STAR
result = response_untagged
else
result = response_tagged
end
match(T_CRLF)
match(T_EOF)
return result
end
end
end
end

adding a 'match(T_SPACE) if lookahead.symbol == T_SPACE' just before the CRLF match:
require 'net/imap'
module Net
class IMAP
class ResponseParser
def response
token = lookahead
case token.symbol
when T_PLUS
result = continue_req
when T_STAR
result = response_untagged
else
result = response_tagged
end
match(T_SPACE) if lookahead.symbol == T_SPACE
match(T_CRLF)
match(T_EOF)
return result
end #def response
end #class ResponseParser
end #class IMAP
end #module Net

I've tested this 'monkeypatched' IMAP class long enough to say that fortunately this is all we need to make our client work... does it means that Microsoft is really shifting towards standards-based technology? Bah!