The GNU Privacy Guard is an essential application when you need to ensure the confidentiality and origin of the information, so it helps to protect your privacy and the people you communicate with.

Installation

Install gnupg utility, gnupg-agent secret key management and pinentry pass-phrase entry dialog (there are QT, GTK, and curses-based versions). I need to mention that these packages should already be installed.

$ sudo apt-get install gnupg gnupg-agent pinentry

Ensure that the GnuPG agent is accessible inside an interactive shell.

$ cat << EOF | tee -a ~/.bashrc
export \$(cat ~/.gpg-agent-info)
gpg-connect-agent /bye 2>/dev/null || eval \$(gpg-agent --daemon --write-env-file) 
EOF

You can use the alternatives system to set the default version of pinentry pass-phrase entry dialog.

$ update-alternatives --display pinentry
update-alternatives --display pinentry
pinentry - auto mode
  link currently points to /usr/bin/pinentry-qt4
/usr/bin/pinentry-gtk-2 - priority 85
  slave pinentry.1.gz: /usr/share/man/man1/pinentry-gtk-2.1.gz
/usr/bin/pinentry-qt4 - priority 95
  slave pinentry.1.gz: /usr/share/man/man1/pinentry-qt4.1.gz
Current 'best' version is '/usr/bin/pinentry-qt4'.
$ sudo update-alternatives --set pinentry /usr/bin/pinentry-gtk-2
update-alternatives: using /usr/bin/pinentry-gtk-2 to provide /usr/bin/pinentry (pinentry) in manual mode

Inspect gnupg, gpg, gpg-agent and gpg-connect-agent the manual page for detailed information.

Symmetric encryption

Symmetric encryption is the oldest and best-known technique that requires cipher and password.

The default cipher is CAST5

Print version information to get a list of supported algorithms.

$ gpg --version
gpg (GnuPG) 1.4.18
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Home: ~/.gnupg
Supported algorithms:
Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

To encrypt project.tgz file using AES192 cipher execute the following command.

$ gpg --output project.tgz.gpg --cipher-algo aes192 --symmetric project.tgz
Use --armor parameter to encode an encrypted file using base64 algorithm.

The decryption process is very straightforward.

$ gpg --output project.tgz --decrypt project.tgz.gpg

You can identify GnuPG encrypted data using a basic file utility.

$ file project.tgz.gpg
project.tgz.gpg: GPG symmetrically encrypted data (AES192 cipher)

Asymmetric encryption

Asymmetric Encryption involves the use of a public and private key.

The public key which is available to anyone is used to encrypt the data, while the private key is used to sign and decrypt data. The private key which is kept secret is stored in symmetrically encrypted form for security reasons.

Generate key pair and revocation certificate

Use the following command to generate a key pair.

$ gpg --gen-key
gpg (GnuPG) 1.4.18; Copyright (C) 2014 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) 2y
Key expires at Wed Nov  1 13:22:01 2017 CET
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) <heinrichh@duesseldorf.de>"
Real name: Milosz
Email address: milosz@example.org
Comment:
You selected this USER-ID:
    "Milosz <milosz@example.org>"
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.
gpg: /home/milosz/.gnupg/trustdb.gpg: trustdb created
gpg: key E5A39B0F 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
gpg: next trustdb check due at 2017-11-01
pub   2048R/E5A39B0F 2015-11-02 [expires: 2017-11-01]
      Key fingerprint = 18FB 283B 902F 680C CCAF  481A A0DD F9A3 E5A3 9B0F
uid                  Milosz <milosz@example.org>
sub   2048R/E061E112 2015-11-02 [expires: 2017-11-01]

Use the following command to list keys.

$ gpg --list-keys
/home/milosz/.gnupg/pubring.gpg
-------------------------------
pub   2048R/E5A39B0F 2015-11-02 [expires: 2017-11-01]
uid                  Milosz <milosz@example.org>
sub   2048R/E061E112 2015-11-02 [expires: 2017-11-01]
</milosz@example.org>

Use the following command to display fingerprints.

$ gpg --fingerprint
/home/milosz/.gnupg/pubring.gpg
-------------------------------
pub   2048R/E5A39B0F 2015-11-02 [expires: 2017-11-01]
      Key fingerprint = 18FB 283B 902F 680C CCAF  481A A0DD F9A3 E5A3 9B0F
uid                  Milosz <milosz@example.org>
sub   2048R/E061E112 2015-11-02 [expires: 2017-11-01]
</milosz@example.org>

Use the following command to list private keys.

$ gpg --list-secret-keys
/home/milosz/.gnupg/secring.gpg
-------------------------------
sec   2048R/E5A39B0F 2015-11-02 [expires: 2017-11-01]
uid                  Milosz <milosz@example.org>
ssb   2048R/E061E112 2015-11-02
</milosz@example.org>

Use the following command to generate a revocation certificate for milosz@example.org key and store it in revoke.asc file.

$ gpg -a -o revoke.asc --gen-revoke "milosz@example.org"
sec  2048R/E5A39B0F 2015-11-02 Milosz <milosz@example.org>
Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 
Enter an optional description; end it with an empty line:
>
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y

You need a passphrase to unlock the secret key for
user: "Milosz <milosz@example.org>"
2048-bit RSA key, ID E5A39B0F, created 2015-11-02
Revocation certificate created.
Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

The revocation certificate was stored in a specified text file.

$ file revoke.asc
revoke.asc: PGP public key block Signature (old)
$ cat revoke.asc
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
Comment: A revocation certificate should follow
iQEfBCABAgAJBQJWN2H+Ah0AAAoJEKDd+aPlo5sPoBoH/1Njg3cdW6pBPIY5/mnD
7noLvnGetfuHP8QWM5dda+sIlWN7E9M+5Lt4qeKA8uOkLA4EwYghIeRgQBYKVbN3
kpwVUVvnbpiBRydQH/s5B9dNnpRLf2YloLfKDU4pw1hDOnkckAFMK2+wIw0hvb3c
OXZtTKfEVe8mRrtsQQIWf0/N0ifo9OtR45JgVVHFhK+X6ypGDZ+o/Cb6zOLizEvn
tlDeR2ZRf19tjtPvB/TJXwqDPX6lWYq7aPjS0WysxpfxQZ0GQ8nRZ8AR364lnbEE
wJatWIZTQlYTPlIrJw/2rGXJHq68u2RpU4ZLcbRW6bravKLvksYkpLFWKNh0Hfor
Cr8=
=W1AA
-----END PGP PUBLIC KEY BLOCK-----

Import revocation certificate to revoke the key.

$ gpg --import revoke.asc
gpg: key E5A39B0F: "Milosz <milosz@example.org>" revocation certificate imported
gpg: Total number processed: 1
gpg:    new key revocations: 1
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
gpg: next trustdb check due at 2017-11-01
$ gpg --list-keys "milosz@example.org"
pub   2048R/E5A39B0F 2015-11-02 [revoked: 2015-11-02]
uid                  Milosz <milosz@example.org>

Export public key

Use the following command to export the public key milosz@example.org and store it in pubkey.asc text file.

$ gpg --output pubkey.asc --armor --export "milosz@example.org"
$ cat pubkey.asc
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQENBFY3VaIBCADKvj8wvwR0XkHr+jjF4T4CN9w94Gq5FGcgbEIgpY1w/v2tf72K
So2UMUqDVChTB+0rXE1YqcqoGKZi8L9X2hdAxjNRGud5b/7iHNmHDKNiKkgHE4FT
hlzAxPjsaVGZ9WxnPUeZ8pIVCuGTima41Onrx3efgZ7sd7ROFA+RY87oW8BezQQW
iaMfDIgekHifrwy3dXN99q6cNug8XW8bJXbbiLrNZuBQYBSv0FHQfhyh9UIyJp53
TPtaNZDVT04XrVAdA8kveANPvks996RlNQp0tg0X853F1mIuPdkCUr6c0KUbz8HS
ACGgwjkVzUZW/FE8lZnEVK3XZ90sIj4eEUsbABEBAAG0G01pbG9zeiA8bWlsb3N6
QGV4YW1wbGUub3JnPokBPgQTAQIAKAUCVjdVogIbAwUJA8JnAAYLCQgHAwIGFQgC
CQoLBBYCAwECHgECF4AACgkQoN35o+Wjmw+0ZwgAsxghzSNBq/+SMJd3WLUn34Th
EWJvdC2Qwowk6OKaPT9n0dlJiFlScRr1rptfeGOZxEoxa68O1bomKAChe1qoW+Kb
gRtB+HFXTporCDX2rNsYN6Up1U9ZDOU9uDOBPDgW+4d29rbw1Ek5/acKqvwAGsla
qsYmyxb8oR+/naQ1U3U4qnysG0xKOrdGRycEr36jmiYD0Uqer+o+43yEuiGJ7Oab
aq6hjB3REaZXOSkQKpcGo6QJQyzlR0e81oqsop7u5xPQCkSxVt3wQJBTnCWz4c1K
Pn1zIdgoZp9qRb59CCxylDzbMyzlrmj7cnW2GxXfGuPTh6Wpk2kbBmrD4Rh+aLkB
DQRWN1WiAQgA3AKOzttTpJiV5Gu8wHfg2EV/ORbjhvyTZEancd3DC1rAQuTLTeGh
ye6G47bT6bIGXnxgxdOR23K3Ml5KaP5z7hOLp+bnjKD3grthhKZr7xWu8DgLPnbZ
ntTw22WfR3FE5NrhS1qjpvk9VtNuQrpxWb/ZHiIhsLxBCj9gk5utSlRbmeKgdc2D
P13tJ43KO77t8xiD4BIflByugXk9/dAbLNwgA/jgBJVqgwKozjqeBsdvaAjo6Bwh
fNW+EYCu0DeHQcGZYyVELplph9dqvmQtJSEzAGPgByx8k+soNsN8CiCOStoEe2dI
SPQhGrijXAfHdvyDoEs/wCjGBEwyAcFPnwARAQABiQElBBgBAgAPBQJWN1WiAhsM
BQkDwmcAAAoJEKDd+aPlo5sPkkYH/3fEQ+Nm36yPmh5VEpJsM4A7Lg9sL0Py1lNj
65G3+bLEkdUVE5rc0TBbJNRunVQWDqU3Bh4MehnRkX45O/WScSOfuuqK4Di+UTEP
OQn3OKGXLVzvQiWVd3lrtTDlBVT8GaeswMjtJLH4B5hEv8TS/CQTsx+16pWrV2GD
jF2FGDLId0o7uPQc0aUgrs5rDuF/OyvCUv0L1E04TVBJheaIjGqlIhmGaz+HoKSq
qFZTBnMVAL5l4cav0UXcM9isMMKUmimy5SQN6xSalyAtPlx9HNpaIHelOQUYhuyj
Z2vxVLgV2Zngn08b3MgXEan9AZ8sa7FiK7L67vjkoIwqgtcu5m4=
=TovX
-----END PGP PUBLIC KEY BLOCK-----
Exclude --armor parameter to store the public key in binary form.

Import public key

Use the following command to import a public key from pubkey_sbs.asc file.

$ gpg --import pubkey_sbs.asc
gpg: key D6833FEF: public key "Milosz <milosz@sleeplessbeastie.eu>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

Verify key fingerprint.

$ gpg --fingerprint "milosz@sleeplessbeastie.eu"
pub   2048R/D6833FEF 2015-11-02 [expires: 2016-11-01]
      Key fingerprint = 12B3 8529 73C0 E602 C647  CABE 7395 85A8 D683 3FEF
uid                  Milosz <milosz@sleeplessbeastie.eu>
sub   2048R/FB8197C2 2015-11-02 [expires: 2016-11-01]

Sign public key

You can sign the public key after you have verified the identity of the other person and confirmed their key fingerprint. It is important to not take it lightly.

Verify key fingerprint.

$ gpg --fingerprint "milosz@sleeplessbeastie.eu"
pub   2048R/D6833FEF 2015-11-02 [expires: 2016-11-01]
      Key fingerprint = 12B3 8529 73C0 E602 C647  CABE 7395 85A8 D683 3FEF
uid                  Milosz <milosz@sleeplessbeastie.eu>
sub   2048R/FB8197C2 2015-11-02 [expires: 2016-11-01]

Use the following command to sign the milosz@sleeplessbeastie.eu public key.

$ gpg --sign-key "milosz@sleeplessbeastie.eu"
pub  2048R/D6833FEF  created: 2015-11-02  expires: 2016-11-01  usage: SC
                     trust: unknown       validity: unknown
sub  2048R/FB8197C2  created: 2015-11-02  expires: 2016-11-01  usage: E
[ unknown] (1). Milosz <milosz@sleeplessbeastie.eu>

pub  2048R/D6833FEF  created: 2015-11-02  expires: 2016-11-01  usage: SC
                     trust: unknown       validity: unknown
 Primary key fingerprint: 12B3 8529 73C0 E602 C647  CABE 7395 85A8 D683 3FEF
     Milosz <milosz@sleeplessbeastie.eu>
This key is due to expire on 2016-11-01.
Are you sure that you want to sign this key with your
key "Milosz <milosz@example.org>" (E5A39B0F)

Really sign? (y/N) y

You need a passphrase to unlock the secret key for
user: "Milosz <milosz@example.org>"
2048-bit RSA key, ID E5A39B0F, created 2015-11-02

Alternatively, you can edit the key to perform the same operation.

$ gpg --edit-key "milosz@sleeplessbeastie.eu"
gpg (GnuPG) 1.4.18; Copyright (C) 2014 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.

pub  2048R/D6833FEF  created: 2015-11-02  expires: 2016-11-01  usage: SC
                     trust: unknown       validity: unknown
sub  2048R/FB8197C2  created: 2015-11-02  expires: 2016-11-01  usage: E
[ unknown] (1). Milosz <milosz@sleeplessbeastie.eu>
gpg> fpr
pub   2048R/D6833FEF 2015-11-02 Milosz <milosz@sleeplessbeastie.eu>
 Primary key fingerprint: 12B3 8529 73C0 E602 C647  CABE 7395 85A8 D683 3FEF
gpg> sign

pub  2048R/D6833FEF  created: 2015-11-02  expires: 2016-11-01  usage: SC
                     trust: unknown       validity: unknown
 Primary key fingerprint: 12B3 8529 73C0 E602 C647  CABE 7395 85A8 D683 3FEF
     Milosz <milosz@sleeplessbeastie.eu>
This key is due to expire on 2016-11-01.
Are you sure that you want to sign this key with your
key "Milosz  <milosz@example.org>" (E5A39B0F)
Really sign? (y/N) y

You need a passphrase to unlock the secret key for
user: "Milosz  <milosz@example.org>"
2048-bit RSA key, ID E5A39B0F, created 2015-11-02
gpg> quit
Save changes? (y/N) y

Delete key

Use the following command to delete the milosz@sleeplessbeastie.eu public key.

$ gpg --delete-key "milosz@sleeplessbeastie.eu"

Use the following command to delete the milosz@example.org key pair.

$ gpg  --delete-secret-and-public-key "milosz@example.org"
gpg (GnuPG) 1.4.18; Copyright (C) 2014 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.

sec  2048R/E5A39B0F 2015-11-02 Milosz <milosz@example.org>
Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y

pub  2048R/E5A39B0F 2015-11-02 Milosz <milosz@example.org>

This is a two-step process as you need to delete the private key (--delete-secret-key parameter) first, then public key (--delete-key parameter).

$ gpg --delete-secret-key "milosz@example.org"
gpg (GnuPG) 1.4.18; Copyright (C) 2014 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.
sec  2048R/E5A39B0F 2015-11-02 Milosz <milosz@example.org>
Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y
$ gpg --delete-key "milosz@example.org"
gpg (GnuPG) 1.4.18; Copyright (C) 2014 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.
pub  2048R/E5A39B0F 2015-11-02 Milosz <milosz@example.org>
Delete this key from the keyring? (y/N) y

File encryption

Use the following command to encrypt project.tgz file using recipient’s public key milosz@sleeplessbeastie.eu.

$ gpg --output project.tgz.gpg --encrypt --armor --recipient "milosz@sleeplessbeastie.eu" project.tgz
Exclude --armor parameter to store the public key in binary form.

Use the following command to decrypt project.tgz.gpg file using a private key.

$ gpg --output project.tgz --decrypt projekt.tgz.gpg

Creating and verifying signatures

The digital signature confirms that the file received from a particular person is in the unchanged form. It is used to confirm the origin and state of the file.

The owner can create a digital signature using a private key, so every other person can verify it using the available public key. There are three distinct types of signature: standard signature (sign), clear text signature (clearsign) and signature stored separately (detached signature).

Standard signature

Use the following command to create project.tgz.asc file including a standard signature for project.tgz file using milosz@example.org private key.

$ gpg --armor --output project.tgz.asc --local-user "milosz@example.org" --sign project.tgz
Exclude --armor parameter to store file including a standard signature in binary form.
$ gpg --output project.tgz.sig --local-user "milosz@example.org" --sign project.tgz

Use the following command to verify project.tgz.asc file.

$ gpg --verify projekt.tgz.asc
gpg: Signature made Mon Nov  2 23:18:53 2015 CET using RSA key ID E5A39B0F
gpg: Good signature from "Milosz <milosz@example.org>"
gpg: WARNING: not a detached signature; file 'project.tgz' was NOT verified!
Use --force-mdc parameter to force the use of modification detection code or --no-mdc-warning to suppress the warning.

Use the following command to extract original project.tgz file (the key is not required).

$ gpg --output project.tgz --decrypt project.tgz.sig
gpg: Signature made Mon Nov  2 23:18:53 2015 CET using RSA key ID E5A39B0F
gpg: Good signature from "Milosz <milosz@example.org>"

Use the following command to sign and encrypt using asymmetric encryption.

$ gpg --armor --output project.tgz.gpg --recipient "milosz@sleeplessbeastie.eu" --encrypt --sign project.tgz

Use the following command to sign and encrypt using symmetric encryption.

$ gpg --armor --output project.tgz.gpg --local-user "milosz@example.org" --symmetric --sign project.tgz

You need to decrypt the file to confirm that signature is valid.

$ gpg --output project.tgz --decrypt project.tgz.gpg
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: Signature made Tue Nov  3 01:52:39 2015 CET using RSA key ID E5A39B0F
gpg: Good signature from "Milosz <milosz@example.org>"

Clear text signature

The main difference between standard and clear text signature is that the second one is human readable.

Use the following command to create fstab.asc file including clear text signature for /etc/fstab file using milosz@example.org private key.

$ gpg --output fstab.asc --local-user "milosz@example.org" --clearsign /etc/fstab

Contents of fstab.asc file.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda1 during installation
UUID=95e5a0d5-e632-4471-9eb4-ee1bc0ad8736 /               ext4    errors=remount-ro 0       1
# swap was on /dev/sda5 during installation
UUID=776373bc-9229-437b-98b1-2ba557056413 none            swap    sw              0       0
/dev/sr0        /media/cdrom0   udf,iso9660 user,noauto     0       0
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAEBAgAGBQJWN/QaAAoJEKDd+aPlo5sPpF4H/2d6fxp0Y4o2o4T7hu3gbLhD
9tUp7GdodenDt/kUYVqE76hDnWK2utIe69bTaeCKJvaTip2qr9X5dH1Q/jMdyVvJ
WFhIm1NC+nhvrCAi7bqZOdTXGim7HlMEnvUXlkz/fKJM9X6Rvh01Tf+PXkCSCSDb
YN613MEYzQYqMPlAmYS3IdkOs4N5PEbMzrUVEqb5ki0/jiGlN82jdKNtImAgmg68
LkXJ6KXJj2Q1mgsa40VJRAqd9dBVqYrtyVq5LgTh63n8ulbQh4l0WmdVE0CgYbLj
nm6VgZl4kZDBD7yp0ug0B3Mc+n9VtkjpEF5fYsTM9Y6clzJ8WnO0mKVgQwDaI3w=
=iLAR
-----END PGP SIGNATURE-----

Use the following command to verify fstab.asc file.

$ gpg --verify fstab.asc
gpg: Signature made Tue Nov  3 00:39:06 2015 CET using RSA key ID E5A39B0F
gpg: Good signature from "Milosz <milosz@example.org>"

Use the following command to extract original fstab file (the key is not required).

$ gpg --output fstab --decrypt fstab.asc
gpg: Signature made Tue Nov  3 00:39:06 2015 CET using RSA key ID E5A39B0F
gpg: Good signature from "Milosz <milosz@example.org>"
</milosz@example.org>

Detached signature

The detached signature is stored separately from the signed file, so you need both of the files to perform the verification process.

Use the following command to create project.tgz.asc detached signature for project.tgz file using milosz@example.org private key.

$ gpg --armor --output project.tgz.asc --local-user "milosz@example.org" --detach-sig project.tgz
Exclude --armor parameter to store the detached signature in binary form.
$ gpg --output project.tgz.sig --local-user "milosz@example.org" --detach-sig project.tgz

Contents of project.tgz.sig file.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAABAgAGBQJWN/4MAAoJEKDd+aPlo5sPrNoH/iUYR2fDRBU82rRRtqxMTCym
4xMZtfaxLWrDHAo+K3BzEzf7RpFhR0ol0JzVLd3weF/DZW4goR652ngVWl7xCpwV
xZMyTXLqlv2ikVkXdyrMJ5jlATiQegMG4Rv9qfrZaUN2aIVwwgZovQ3wWvFTXZ0B
UGfQKbaooOcAM7137MTdcRndSDRhF2bmQSNbVkjVRqaJcG/W/8aWx145r/sDI+dX
TOZExfJ9anbBDIvtDXwyQgmPb+VVQpjDvFIFLerTrNOSKpkA1y7xVDCNfzp3vAra
oNcOCbZea8pkm4UfDe7JcEvWu8UBjwihz+VtwOmWSizZUuVyckaTgrCyMrggyzE=
=K42U
-----END PGP SIGNATURE-----

Use the following command to verify project.tgz.asc file.

gpg --verify project.tgz.sig project.tgz
gpg: Signature made Tue Nov  3 01:22:13 2015 CET using RSA key ID E5A39B0F
gpg: Good signature from "Milosz <milosz@example.org>"

Specifying encryption parameters will encrypt the detached signature.

Key servers

Using a public key server significantly simplifies the key exchange process.

Use the following command to list keys.

$ gpg --list-keys
/home/milosz/.gnupg/pubring.gpg
-------------------------------
pub   1024D/992CDB5D 2009-01-25
uid                  Milosz <milosz@examle.com>
sub   2048g/2FFFE4AE 2009-01-25

Use the following command to send 992CDB5D key.

$ gpg --keyserver wwwkeys.pgp.net --send-key 992CDB5D
gpg: sending key 992CDB5D to hkp server wwwkeys.pgp.net

Use the following command to search for milosz@example.org key and import it.

$ gpg --keyserver wwwkeys.pgp.net --search-key milosz@example.org
gpg: searching for "milosz@example.org" from hkp server wwwkeys.pgp.net
(1) Milosz <milosz@example.org>
   1024 bit DSA key 992CDB5D, created: 2009-01-25
Keys 1-1 of 1 for "milosz@example.org".  Enter number(s), N)ext, or Q)uit > 1
gpg: requesting key 992CDB5D from hkp server wwwkeys.pgp.net
gpg: key 992CDB5D: public key "Milosz <milosz@example.org>" imported
gpg: Total number processed: 1
gpg:               imported: 1

Use the following command to send 992CDB5D key.

% gpg --keyserver wwwkeys.pgp.net --recv-key 992CDB5D
gpg: requesting key 992CDB5D from hkp server wwwkeys.pgp.net
gpg: key 992CDB5D: public key "Milosz <milosz@example.org>" imported
gpg: Total number processed: 1
gpg:               imported: 1

References

Gnu Privacy Guard manual
Gnu Privacy Guard FAQ
comp.security.pgp FAQ
GPG Keysigning Party HOWTO