Difference between revisions of "HowTo:PGP"
(Created page with "Online services are the foundation of distributed computing, but security is often overlooked at the beginnings of these projects. Here, I'll explain a really simple way to lock…") |
m (→Create a Keyring) |
||
Line 28: | Line 28: | ||
gpg --gen-key |
gpg --gen-key |
||
</source> |
</source> |
||
− | <pre> |
||
+ | <pre class="mw-collapsible mw-collapsed"> |
||
gpg (GnuPG) 1.4.13; Copyright (C) 2012 Free Software Foundation, Inc. |
gpg (GnuPG) 1.4.13; Copyright (C) 2012 Free Software Foundation, Inc. |
||
This is free software: you are free to change and redistribute it. |
This is free software: you are free to change and redistribute it. |
||
Line 54: | Line 54: | ||
You need a user ID to identify your key; the software constructs the user ID |
You need a user ID to identify your key; the software constructs the user ID |
||
from the Real Name, Comment and Email Address in this form: |
from the Real Name, Comment and Email Address in this form: |
||
− | "Heinrich Heine (Der Dichter) < |
+ | "Heinrich Heine (Der Dichter) <heinrichhduesseldorf.de>" |
Real name: David M. Rogers |
Real name: David M. Rogers |
||
− | Email address: |
+ | Email address: predictivestatmechgmail.com |
Comment: |
Comment: |
||
You selected this USER-ID: |
You selected this USER-ID: |
||
− | "David M. Rogers < |
+ | "David M. Rogers <predictivestatmechgmail.com>" |
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o |
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o |
||
Line 84: | Line 84: | ||
pub 2048R/262B259C 2013-12-20 |
pub 2048R/262B259C 2013-12-20 |
||
Key fingerprint = D1CE 9C6A 5099 6753 8FC4 81F5 5B64 9362 262B 259C |
Key fingerprint = D1CE 9C6A 5099 6753 8FC4 81F5 5B64 9362 262B 259C |
||
− | uid David M. Rogers < |
+ | uid David M. Rogers <predictivestatmechgmail.com> |
sub 2048R/E494F149 2013-12-20 |
sub 2048R/E494F149 2013-12-20 |
||
</pre> |
</pre> |
||
Line 130: | Line 130: | ||
You need a user ID to identify your key; the software constructs the user ID |
You need a user ID to identify your key; the software constructs the user ID |
||
from the Real Name, Comment and Email Address in this form: |
from the Real Name, Comment and Email Address in this form: |
||
− | "Heinrich Heine (Der Dichter) < |
+ | "Heinrich Heine (Der Dichter) <heinrichhduesseldorf.de>" |
Real name: kubotan |
Real name: kubotan |
||
− | Email address: |
+ | Email address: davidrogersusf.edu |
Comment: MBPR Laptop |
Comment: MBPR Laptop |
||
You selected this USER-ID: |
You selected this USER-ID: |
||
− | "kubotan (MBPR Laptop) < |
+ | "kubotan (MBPR Laptop) <davidrogersusf.edu>" |
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o |
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o |
||
Line 159: | Line 159: | ||
pub 2048R/03357392 2013-12-20 [expires: 2016-12-19] |
pub 2048R/03357392 2013-12-20 [expires: 2016-12-19] |
||
Key fingerprint = C417 3765 AB3A 139B 72C3 F093 D35C FD07 0335 7392 |
Key fingerprint = C417 3765 AB3A 139B 72C3 F093 D35C FD07 0335 7392 |
||
− | uid kubotan (MBPR Laptop) < |
+ | uid kubotan (MBPR Laptop) <davidrogersusf.edu> |
Note that this key cannot be used for encryption. You may want to use |
Note that this key cannot be used for encryption. You may want to use |
||
Line 178: | Line 178: | ||
pub 2048R/03357392 created: 2013-12-20 expires: 2016-12-19 usage: SC |
pub 2048R/03357392 created: 2013-12-20 expires: 2016-12-19 usage: SC |
||
trust: ultimate validity: ultimate |
trust: ultimate validity: ultimate |
||
− | [ultimate] (1). kubotan (MBPR Laptop) < |
+ | [ultimate] (1). kubotan (MBPR Laptop) <davidrogersusf.edu> |
gpg> sign |
gpg> sign |
||
Line 186: | Line 186: | ||
Primary key fingerprint: C417 3765 AB3A 139B 72C3 F093 D35C FD07 0335 7392 |
Primary key fingerprint: C417 3765 AB3A 139B 72C3 F093 D35C FD07 0335 7392 |
||
− | kubotan (MBPR Laptop) < |
+ | kubotan (MBPR Laptop) <davidrogersusf.edu> |
This key is due to expire on 2016-12-19. |
This key is due to expire on 2016-12-19. |
||
Are you sure that you want to sign this key with your |
Are you sure that you want to sign this key with your |
||
− | key "David M. Rogers < |
+ | key "David M. Rogers <predictivestatmechgmail.com>" (262B259C) |
Really sign? (y/N) y |
Really sign? (y/N) y |
||
You need a passphrase to unlock the secret key for |
You need a passphrase to unlock the secret key for |
||
− | user: "David M. Rogers < |
+ | user: "David M. Rogers <predictivestatmechgmail.com>" |
2048-bit RSA key, ID 262B259C, created 2013-12-20 |
2048-bit RSA key, ID 262B259C, created 2013-12-20 |
||
Line 203: | Line 203: | ||
</pre> |
</pre> |
||
− | My signature belongs to kubotan's key now, so GPG saves |
+ | My signature belongs to kubotan's key now, so GPG saves it there. |
− | <source lang="bash" |
+ | <source lang="bash"> |
gpg --list-sigs |
gpg --list-sigs |
||
</source> |
</source> |
||
+ | |||
<pre> |
<pre> |
||
gpg: checking the trustdb |
gpg: checking the trustdb |
||
Line 215: | Line 216: | ||
-------------------------------- |
-------------------------------- |
||
pub 2048R/262B259C 2013-12-20 |
pub 2048R/262B259C 2013-12-20 |
||
− | uid David M. Rogers < |
+ | uid David M. Rogers <predictivestatmechgmail.com> |
− | sig 3 262B259C 2013-12-20 David M. Rogers < |
+ | sig 3 262B259C 2013-12-20 David M. Rogers <predictivestatmechgmail.com> |
sub 2048R/E494F149 2013-12-20 |
sub 2048R/E494F149 2013-12-20 |
||
− | sig 262B259C 2013-12-20 David M. Rogers < |
+ | sig 262B259C 2013-12-20 David M. Rogers <predictivestatmechgmail.com> |
pub 2048R/03357392 2013-12-20 [expires: 2016-12-19] |
pub 2048R/03357392 2013-12-20 [expires: 2016-12-19] |
||
− | uid kubotan (MBPR Laptop) < |
+ | uid kubotan (MBPR Laptop) <davidrogersusf.edu> |
− | sig 3 03357392 2013-12-20 kubotan (MBPR Laptop) < |
+ | sig 3 03357392 2013-12-20 kubotan (MBPR Laptop) <davidrogersusf.edu> |
− | sig 262B259C 2013-12-20 David M. Rogers < |
+ | sig 262B259C 2013-12-20 David M. Rogers <predictivestatmechgmail.com> |
</pre> |
</pre> |
||
Revision as of 16:56, 20 December 2013
Online services are the foundation of distributed computing, but security is often overlooked at the beginnings of these projects. Here, I'll explain a really simple way to lock down access to your precious protocols at the transport layer. There are essentially no changes required to the communication protocol. In addition, the method dovetails with the GnuPG suite for message signature and encryption.
Contents
Get Started with GnuPG
Why?
GnuPG uses a chain of public-key certificates, similar to the x.509 certificates that we're all familiar with our web-browsers constantly complaining about. Each certificate has some private information (that the owner keeps) and some identifying public information that is distributed like a user-id, name and birthdate, or the like. The difference with those other numbers is that revealing the public key doesn't compromise your security, like a password social security number would. Instead, the public key is used to check that a communication could only have come from the person knowing the private key.
Things get complicated when more than two people get involved. How do I know a person's public key is trusted to do something? PGP does this by having one key sign another key. If I want my webserver to recognize a set of users, I can create a server private key and use it to sign the public keys of trusted users. Then I have a chain of signatures that validate the user's public key. When the user connects, I use that public key to make sure the user knows the corresponding private key.
Secure internet servers use x.509 certificates in a similar way to prove that you can trust them. Your browser has a list of trusted root certificates from places like Verisign and Thawte. When you connect to a random server using HTTPS, the server gives you a public key. Your browser then checks whether that public key has been signed by one of the trusted root certificates it knows about.
Although similar to x.509 server certificates, PGP doesn't have a centrally based set of trusted root certificate authorities. In fact, anyone can sign for anyone else in the PGP scheme. This makes it much more user-centric. I can, for example, sign source code packages I produce and people who have my public key can verify that they haven't been tampered with. I could produce a hierarchy of keys to sign things like code, purchase orders, or server access. I could use these to delegate those responsibilities. At the same time, I could get those keys signed by other people (like the manager of a coding project, an accountant, or a server admin).
Install
Use a package-manager to look for a gnupg or equivalent. <source lang="bash"> apt-get install gnupg # Trisquel / Debian / Mint / Ubuntu fink install gnupg # OSX + Fink yum install gnupg # RHEL / Centos / Scientific Linux / Fedora </source>
Create a Keyring
GnuPG does almost everything through options to the gpg command. Following along with,[1] <source lang="bash"> gpg --gen-key </source>
gpg (GnuPG) 1.4.13; Copyright (C) 2012 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? 1 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) Key does not expire at all Is this correct? (y/N) y You need a user ID to identify your key; the software constructs the user ID from the Real Name, Comment and Email Address in this form: "Heinrich Heine (Der Dichter) <heinrichhduesseldorf.de>" Real name: David M. Rogers Email address: predictivestatmechgmail.com Comment: You selected this USER-ID: "David M. Rogers <predictivestatmechgmail.com>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o You need a Passphrase to protect your secret key. We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. . We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. . gpg: ~/.gnupg/trustdb.gpg: trustdb created gpg: key 262B259C marked as ultimately trusted public and secret key created and signed. gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u pub 2048R/262B259C 2013-12-20 Key fingerprint = D1CE 9C6A 5099 6753 8FC4 81F5 5B64 9362 262B 259C uid David M. Rogers <predictivestatmechgmail.com> sub 2048R/E494F149 2013-12-20
Next, you'll want to double-check that it worked and make sure gnupg's directory has no read or write permissions for anyone other than yourself. <source lang="bash"> gpg --list-keys ls -ld ~/.gnupg </source>
For the client/server example, we'll also want to write the public key to a separate file. <source lang="bash"> gpg --export 262B259C --ascii >~/.gnupg/predictivestatmech.asc </source>
Next, we'll generate a certificate belonging to my laptop. I'll choose to use this one for allowing users to connect to a new protocol I'm developing. It can't have a password according the GNUTLS manual. <source lang="bash"> gpg --gen-key </source>
gpg (GnuPG) 1.4.13; Copyright (C) 2012 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? 4 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 3y Key expires at Mon Dec 19 15:04:37 2016 EST Is this correct? (y/N) y You need a user ID to identify your key; the software constructs the user ID from the Real Name, Comment and Email Address in this form: "Heinrich Heine (Der Dichter) <heinrichhduesseldorf.de>" Real name: kubotan Email address: davidrogersusf.edu Comment: MBPR Laptop You selected this USER-ID: "kubotan (MBPR Laptop) <davidrogersusf.edu>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o You need a Passphrase to protect your secret key. You don't want a passphrase - this is probably a *bad* idea! I will do it anyway. You can change your passphrase at any time, using this program with the option "--edit-key". We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. . gpg: key 03357392 marked as ultimately trusted public and secret key created and signed. gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u gpg: next trustdb check due at 2016-12-19 pub 2048R/03357392 2013-12-20 [expires: 2016-12-19] Key fingerprint = C417 3765 AB3A 139B 72C3 F093 D35C FD07 0335 7392 uid kubotan (MBPR Laptop) <davidrogersusf.edu> Note that this key cannot be used for encryption. You may want to use the command "--edit-key" to generate a subkey for this purpose.
Following the suggestion, I'll sign this one with my user key. <source lang="bash"> gpg --edit-key kubotan </source>
gpg (GnuPG) 1.4.13; Copyright (C) 2012 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Secret key is available. pub 2048R/03357392 created: 2013-12-20 expires: 2016-12-19 usage: SC trust: ultimate validity: ultimate [ultimate] (1). kubotan (MBPR Laptop) <davidrogersusf.edu> gpg> sign pub 2048R/03357392 created: 2013-12-20 expires: 2016-12-19 usage: SC trust: ultimate validity: ultimate Primary key fingerprint: C417 3765 AB3A 139B 72C3 F093 D35C FD07 0335 7392 kubotan (MBPR Laptop) <davidrogersusf.edu> This key is due to expire on 2016-12-19. Are you sure that you want to sign this key with your key "David M. Rogers <predictivestatmechgmail.com>" (262B259C) Really sign? (y/N) y You need a passphrase to unlock the secret key for user: "David M. Rogers <predictivestatmechgmail.com>" 2048-bit RSA key, ID 262B259C, created 2013-12-20 gpg> quit Save changes? (y/N) y
My signature belongs to kubotan's key now, so GPG saves it there. <source lang="bash"> gpg --list-sigs </source>
gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u gpg: next trustdb check due at 2016-12-19 /Users/rogers/.gnupg/pubring.gpg -------------------------------- pub 2048R/262B259C 2013-12-20 uid David M. Rogers <predictivestatmechgmail.com> sig 3 262B259C 2013-12-20 David M. Rogers <predictivestatmechgmail.com> sub 2048R/E494F149 2013-12-20 sig 262B259C 2013-12-20 David M. Rogers <predictivestatmechgmail.com> pub 2048R/03357392 2013-12-20 [expires: 2016-12-19] uid kubotan (MBPR Laptop) <davidrogersusf.edu> sig 3 03357392 2013-12-20 kubotan (MBPR Laptop) <davidrogersusf.edu> sig 262B259C 2013-12-20 David M. Rogers <predictivestatmechgmail.com>
I need both its public and private sections to use in the server code, so I'll extract them, and mark them self-read-only. <source lang="bash"> gpg --armor --export "kubotan" >~/.gnupg/kubotan.asc gpg --armor --export-secret-key "kubotan" >~/.gnupg/kubotan-secret.asc chmod 400 ~/.gnupg/*.asc </source>
These keys are all you need to sign or encrypt messages as well. To see the usage for those, check the chapters in the GPG Mini-Howto.
Server
Next, let's get started with some client/server code. TLS stands for transport-layer-security. Normal communications (e.g. http/telnet/ftp) merrily go about sending messages (commands, files, output, etc.) over TCP. TLS-enabled communications (e.g. HTTPS/SSH/SFTP) start a connection by figuring out how to encrypt the session. They can also check signatures to authenticate the user and the server. After that, all communications are encrypted to prevent data leaking to the local packet sniffing red-team.
Although incorporating a 'STARTTLS' message into your protocol has been recommended if you need to talk before authenticating, the lazy way is to just authenticate and start TLS at connection. The GNU TLS library makes this especially easy by handling certificates, doing the initial TLS handshake, and encrypting/decrypting messages passed through gnutls_record_send / gnutls_record_recv.
Installation
The GNUTLS library is under heavy development, and I found that the examples in the manual[2] would not run with the package manager's version 2.2. So, I installed nettle 2.7.1 (--enable-shared) and gnutls 3.2.7[3] from source. Apparently someone's been using strerror in gnutls, and someone else has been replacing strerror with repl_strerror to teach them a lesson - so we have to deal with the collateral damage. <source lang="bash">
sed -i.bak -e 's|strerror([^)]*)|""|g' lib/nettle/egd.c sed -i.bak -e 's|strerror([^)]*)|""|g' lib/nettle/rnd.c
</source>
Usage
The server code for OpenPGP authentication and client code for the very similar x.509 authentication are available. Between those two and the code for verifying a certificate, we can hack together a client/server pair authenticating using OpenPGP.
I'm in the process of adding this to the libixp library for authenticated 9P sessions.