Posts Tagged ‘encryption’

Risks and Countermeasures to the Management of Application Secrets

September 17, 2015

Risks

  • Passwords and other secrets for things like data-stores, syslog servers, monitoring services, email accounts and so on can be useful to an attacker to compromise data-stores, obtain further secrets from email accounts, file servers, system logs, services being monitored, etc, and may even provide credentials to continue moving through the network compromising other machines.
  • Passwords and/or their hashes travelling over the network.

Data-store Compromise

Exploitability

The reason I’ve tagged this as moderate is because if you take the countermeasures, it doesn’t have to be a disaster.

There are many examples of this happening on a daily basis to millions of users. The Ashley Madison debacle is a good example. Ashley Madison’s entire business relied on its commitment to keep its clients (37 million of them) data secret, provide discretion and anonymity.

Before the breach, the company boasted about airtight data security but ironically, still proudly displays a graphic with the phrase “trusted security award” on its homepage

We worked hard to make a fully undetectable attack, then got in and found nothing to bypass…. Nobody was watching. No security. Only thing was segmented network. You could use Pass1234 from the internet to VPN to root on all servers.

Any CEO who isn’t vigilantly protecting his or her company’s assets with systems designed to track user behavior and identify malicious activity is acting negligently and putting the entire organization at risk. And as we’ve seen in the case of Ashley Madison, leadership all the way up to the CEO may very well be forced out when security isn’t prioritized as a core tenet of an organization.

Dark Reading

Other notable data-store compromises were LinkedIn with 6.5 million user accounts compromised and 95% of the users passwords cracked in days. Why so fast? Because they used simple hashing, specifically SHA-1. EBay with 145 million active buyers. Many others coming to light regularly.

Are you using well salted and quality strong key derivation functions (KDFs) for all of your sensitive data? Are you making sure you are notifying your customers about using high quality passwords? Are you informing them what a high quality password is? Consider checking new user credentials against a list of the most frequently used and insecure passwords collected.

Countermeasures

Secure password management within applications is a case of doing what you can, often relying on obscurity and leaning on other layers of defence to make it harder for compromise. Like many of the layers already discussed in my book.

Find out how secret the data that is supposed to be secret that is being sent over the network actually is and consider your internal network just as malicious as the internet. Then you will be starting to get the idea of what defence in depth is about. That way when one defence breaks down, you will still be in good standing.

defence in depth

You may read in many places that having data-store passwords and other types of secrets in configuration files in clear text is an insecurity that must be addressed. Then when it comes to mitigation, there seems to be a few techniques for helping, but most of them are based around obscuring the secret rather than securing it. Essentially just making discovery a little more inconvenient like using an alternative port to SSH to other than the default of 22. Maybe surprisingly though, obscurity does significantly reduce the number of opportunistic type attacks from bots and script kiddies.

Store Configuration in Configuration files

Prevention

Do not hard code passwords in source files for all developers to see. Doing so also means the code has to be patched when services are breached. At the very least, store them in configuration files and use different configuration files for different deployments and consider keeping them out of source control.

Here are some examples using the node-config module.

node-config

is a fully featured, well maintained configuration package that I have used on a good number of projects.

To install: From the command line within the root directory of your NodeJS application, run:

npm install node-config --save

Now you are ready to start using node-config. An example of the relevant section of an app.js file may look like the following:

// Due to bug in node-config the if statement is required before config is required
// https://github.com/lorenwest/node-config/issues/202
if (process.env.NODE_ENV === 'production')
   process.env.NODE_CONFIG_DIR = path.join(__dirname, 'config');

Where ever you use node-config, in your routes for example:

var config = require('config');
var nodemailer = require('nodemailer');
var enquiriesEmail = config.enquiries.email;

// Setting up email transport.
var transporter = nodemailer.createTransport({
   service: config.enquiries.service,
   auth: {
      user: config.enquiries.user,
      pass: config.enquiries.pass // App specific password.
   }
});

A good collection of different formats can be used for the config files: .json, .json5, .hjson, .yaml.js, .coffee, .cson, .properties, .toml

There is a specific file loading order which you specify by file naming convention, which provides a lot of flexibility and which caters for:

  • Having multiple instances of the same application running on the same machine
  • The use of short and full host names to mitigate machine naming collisions
  • The type of deployment. This can be anything you set the $NODE_ENV environment variable to for example: development, production, staging, whatever.
  • Using and creating config files which stay out of source control. These config files have a prefix of local. These files are to be managed by external configuration management tools, build scripts, etc. Thus providing even more flexibility about where your sensitive configuration values come from.

The config files for the required attributes used above may take the following directory structure:

OurApp/
|
+-- config/
| |
| +-- default.js (usually has the most in it)
| |
| +-- devbox1-development.js
| |
| +-- devbox2-development.js
| |
| +-- stagingbox-staging.js
| |
| +-- prodbox-production.js
| |
| +-- local.js (creted by build)
|
+-- routes
| |
| +-- home.js
| |
| +-- ...
|
+-- app.js (entry point)
|
+-- ...

The contents of the above example configuration files may look like the following:

module.exports = {
   enquiries: {
      // Supported services:
      // https://github.com/andris9/nodemailer-wellknown#supported-services
      // supported-services actually use the best security settings by default.
      // I tested this with a wire capture, because it is always the most fool proof way.
      service: 'FastMail',
      email: 'yourusername@fastmail.com',
      user: 'yourusername',
      pass: null
   }
   // Lots of other settings.
   // ...
}
module.exports = {
   enquiries: {
      // Test password for developer on devbox1
      pass: 'D[6F9,4fM6?%2ULnirPVTk#Q*7Z+5n' // App specific password.
   }
}
module.exports = {
   enquiries: {
      // Test password for developer on devbox2
      pass: 'eUoxK=S9<,`@m0T1=^(EZ#61^5H;.H' // App specific password.
   }
}
{
}
{
}
// Build creates this file.
module.exports = {
   enquiries: {
      // Password created by the build.
      pass: '10lQu$4YC&x~)}lUF>3pm]Tk>@+{N]' // App specific password.
   }
}

node-config also:

  • Provides command line overrides, thus allowing you to override configuration values at application start from command
  • Allows for the overriding of environment variables with custom environment variables from a custom-environment-variables.json file

Encrypting/decrypting credentials in code may provide some obscurity, but not much more than that.
There are different answers for different platforms. None of which provide complete security, if there is such a thing, but instead focusing on different levels of obscurity.

Windows

Store database credentials as a Local Security Authority (LSA) secret and create a DSN with the stored credential. Use a SqlServer connection string with Trusted_Connection=yes

The hashed credentials are stored in the SAM file and the registry. If an attacker has physical access to the storage, they can easily copy the hashes if the machine is not running or can be shut-down. The hashes can be sniffed from the wire in transit. The hashes can be pulled from the running machines memory (specifically the Local Security Authority Subsystem Service (LSASS.exe)) using tools such as Mimikatz, WCE, hashdump or fgdump. An attacker generally only needs the hash. Trusted tools like psexec take care of this for us. All discussed in my “0wn1ng The Web” presentation.

Encrypt Sections of a web, executable, machine-level, application-level configuration files with aspnet_regiis.exe with the -pe option and name of the configuration element to encrypt and the configuration provider you want to use. Either DataProtectionConfigurationProvider (uses DPAPI) or RSAProtectedConfigurationProvider (uses RSA). the -pd switch is used to decrypt or programatically:

string connStr = ConfigurationManager.ConnectionString["MyDbConn1"].ToString();

Of course there is a problem with this also. DPAPI uses LSASS, which again an attacker can extract the hash from its memory. If the RSAProtectedConfigurationProvider has been used, a key container is required. Mimikatz will force an export from the key container to a .pvk file. Which can then be read using OpenSSL or tools from the Mono.Security assembly.

I have looked at a few other ways using PSCredential and SecureString. They all seem to rely on DPAPI which as mentioned uses LSASS which is open for exploitation.

Credential Guard and Device Guard leverage virtualisation-based security. By the look of it still using LSASS. Bromium have partnered with Microsoft and coined it Micro-virtualization. The idea is that every user task is isolated into its own micro-VM. There seems to be some confusion as to how this is any better. Tasks still need to communicate outside of their VM, so what is to stop malicious code doing the same? I have seen lots of questions but no compelling answers yet. Credential Guard must run on physical hardware directly. Can not run on virtual machines. This alone rules out many
deployments.

Bromium vSentry transforms information and infrastructure protection with a revolutionary new architecture that isolates and defeats advanced threats targeting the endpoint through web, email and documents

vSentry protects desktops without requiring patches or updates, defeating and automatically discarding all known and unknown malware, and eliminating the need for costly remediation.

This is marketing talk. Please don’t take this literally.

vSentry empowers users to access whatever information they need from any network, application or website, without risk to the enterprise

Traditional security solutions rely on detection and often fail to block targeted attacks which use unknown “zero day” exploits. Bromium uses hardware enforced isolation to stop even “undetectable” attacks without disrupting the user.

Bromium

With Bromium micro-virtualization, we now have an answer: A desktop that is utterly secure and
a joy to use

Bromium

These seem like bold claims.

Also worth considering is that Microsofts new virtualization-based security also relies on UEFI Secure Boot, which has been proven insecure.

Linux

Containers also help to provide some form of isolation. Allowing you to only have the user accounts to do what is necessary for the application.

I usually use a deployment tool that also changes the permissions and ownership of the files involved with the running web application to a single system user, so unprivileged users can not access the web applications files at all. The deployment script is executed over SSH in a remote shell. Only specific commands on the server are allowed to run and a very limited set of users have any sort of access to the machine. If you are using Linux Containers then you can reduce this even more if it is not already.

One of the beauties of GNU/Linux is that you can have as much or little security as you decide. No one has made that decision for you already and locked you out of the source. You are not feed lies like all of the closed source OS vendors trying to pimp their latest money spinning product. GNU/Linux is a dirty little secrete that requires no marketing hype. It just provides complete control if you want it. If you do not know what you want, then someone else will probably take that control from you. It is just a matter of time if it hasn’t happened already.

Least Privilege

Prevention

An application should have the least privileges possible in order to carry out what it needs to do. Consider creating accounts for each trust distinction. For example where you only need to read from a data store, then create that connection with a users credentials that is only allowed to read, and so on for other privileges. This way the attack surface is minimised. Adhering to the principle of least privilege. Also consider removing table access completely from the application and only provide permissions to the application to run stored queries. This way if/when an attacker is able to
compromise the machine and retrieve the password for an action on the data-store, they will not be able to do a lot anyway.

Location

Prevention

Put your services like data-stores on network segments that are as sheltered as possible and only contain similar services.

Maintain as few user accounts on the servers in question as possible and with the least privileges as possible.

Data-store Compromise

Prevention

As part of your defence in depth strategy, you should expect that your data-store is going to get stolen, but hope that it does not. What assets within the data-store are sensitive? How are you going to stop an attacker that has gained access to the data-store from making sense of the sensitive data?

As part of developing the application that uses the data-store, a strategy also needs to be developed and implemented to carry on business as usual when this happens. For example, when your detection mechanisms realise that someone unauthorised has been on the machine(s) that host your data-store, as well as the usual alerts being fired off to the people that are going to investigate and audit, your application should take some automatic measures like:

  • All following logins should be instructed to change passwords

If you follow the recommendations below, data-store theft will be an inconvenience, but not a disaster.

Consider what sensitive information you really need to store. Consider using the following key derivation functions (KDFs) for all sensitive data. Not just passwords. Also continue to remind your customers to always use unique passwords that are made up of alphanumeric, upper-case, lower-case and special characters. It is also worth considering pushing the use of high quality password vaults. Do not limit password lengths. Encourage long passwords.

PBKDF2, bcrypt and scrypt are KDFs that are designed to be slow. Used in a process commonly known as key stretching. The process of key stretching in terms of how long it takes can be tuned by increasing or decreasing the number of cycles used. Often 1000 cycles or more for passwords. “The function used to protect stored credentials should balance attacker and defender verification. The defender needs an acceptable response time for verification of users’ credentials during peak use. However, the time required to map <credential> -> <protected form> must remain beyond threats’ hardware (GPU, FPGA) and technique (dictionary-based, brute force, etc) capabilities.

OWASP Password Storage

PBKDF2, bcrypt and the newer scrypt, apply a Pseudorandom Function (PRF) such as a crypto-graphic hash, cipher or HMAC to the data being received along with a unique salt. The salt should be stored with the hashed data.

Do not use MD5, SHA-1 or the SHA-2 family of cryptographic one-way hashing functions by themselves for cryptographic purposes like hashing your sensitive data. In-fact do not use hashing functions at all for this unless they are leveraged with one of the mentioned KDFs. Why? Because the hashing speed can not be slowed as hardware continues to get faster. Many organisations that have had their data-stores stolen and continue to on a weekly basis could avoid their secrets being compromised simply by using a decent KDF with salt and a decent number of iterations. “Using four AMD Radeon HD6990 graphics cards, I am able to make about 15.5 billion guesses per second using the SHA-1 algorithm.

Per Thorsheim

In saying that, PBKDF2 can use MD5, SHA-1 and the SHA-2 family of hashing functions. Bcrypt uses the Blowfish (more specifically the Eksblowfish) cipher. Scrypt does not have user replaceable parts like PBKDF2. The PRF can not be changed from SHA-256 to something else.

Which KDF To Use?

This depends on many considerations. I am not going to tell you which is best, because there is no best. Which to use depends on many things. You are going to have to gain understanding into at least all three KDFs. PBKDF2 is the oldest so it is the most battle tested, but there has also been lessons learnt from it that have been taken to the latter two. The next oldest is bcrypt which uses the Eksblowfish cipher which was designed specifically for bcrypt from the blowfish cipher, to be very slow to initiate thus boosting protection against dictionary attacks which were often run on custom Application-specific Integrated Circuits (ASICs) with low gate counts, often found in GPUs of the day (1999).
The hashing functions that PBKDF2 uses were a lot easier to get speed increases due to ease of parallelisation as opposed to the Eksblowfish cipher attributes such as: far greater memory required for each hash, small and frequent pseudo-random memory accesses, making it harder to cache the data into faster memory. Now with hardware utilising large Field-programmable Gate Arrays (FPGAs), bcrypt brute-forcing is becoming more accessible due to easily obtainable cheap hardware such as:

The sensitive data stored within a data-store should be the output of using one of the three key derivation functions we have just discussed. Feed with the data you want protected and a salt. All good frameworks will have at least PBKDF2 and bcrypt APIs

bcrypt brute-forcing

With well ordered rainbow tables and hardware with high FPGA counts, brute-forcing bcrypt is now feasible:

Risks that Solution Causes

Reliance on adjacent layers of defence means those layers have to actually be up to scratch. There is a possibility that they will not be.

Possibility of missing secrets being sent over the wire.

Possible reliance on obscurity with many of the strategies I have seen proposed. Just be aware that obscurity may slow an attacker down a little, but it will not stop them.

Store Configuration in Configuration files

With moving any secrets from source code to configuration files, there is a possibility that the secrets will not be changed at the same time. If they are not changed, then you have not really helped much, as the secrets are still in source control.

With good configuration tools like node-config, you are provided with plenty of options of splitting up meta-data, creating overrides, storing different parts in different places, etc. There is a risk that you do not use the potential power and flexibility to your best advantage. Learn the ins and outs of what ever system it is you are using and leverage its features to do the best at obscuring your secrets and if possible securing them.

node-config

Is an excellent configuration package with lots of great features. There is no security provided with node-config, just some potential obscurity. Just be aware of that, and as discussed previously, make sure surrounding layers have beefed up security.

Windows

As is often the case with Microsoft solutions, their marketing often leads people to believe that they have secure solutions to problems when that is not the case. As discussed previously, there are plenty of ways to get around the Microsoft so called security features. As anything else in this space, they may provide some obscurity, but do not depend on them being secure.

Statements like the following have the potential for producing over confidence:

vSentry protects desktops without requiring patches or updates, defeating and automatically discarding all known and unknown malware, and eliminating the need for costly remediation.

Bromium

Please keep your systems patched and updated.

With Bromium micro-virtualization, we now have an answer: A desktop that is utterly secure and a joy to use

Bromium

There is a risk that people will believe this.

Linux

As with Microsofts “virtualisation-based security” Linux containers may slow system compromise down, but a determined attacker will find other ways to get around container isolation. Maintaining a small set of user accounts is a worthwhile practise, but that alone will not be enough to stop a highly skilled and determined attacker moving forward.
Even when technical security is very good, an experienced attacker will use other mediums to gain what they want, like social engineering, physical compromise, both, or some other attack vectors. Defence in depth is crucial in achieving good security. Concentrating on the lowest hanging fruit first and working your way up the tree.

Locking file permissions and ownership down is good, but that alone will not save you.

Least Privilege

Applying least privilege to everything can take quite a bit of work. Yes, it is probably not that hard to do, but does require a breadth of thought and time. Some of the areas discussed could be missed. Having more than one person working on the task is often effective as each person can bounce ideas off of each other and the other person is likely to notice areas that you may have missed and visa-versa.

Location

Segmentation is useful, and a common technique to helping to build resistance against attacks. It does introduce some complexity though. With complexity comes the added likely-hood of introducing a fault.

Data-store Compromise

If you follow the advice in the countermeasures section, you will be doing more than most other organisations in this area. It is not hard, but if implemented could increase complacency/over confidence. Always be on your guard. Always expect that although you have done a lot to increase your security stance, a determined and experienced attacker is going to push buttons you may have never realised you had. If they want something enough and have the resources and determination to get it, they probably will. This is where you need strategies in place to deal with post compromise. Create process (ideally partly automated) to deal with theft.

Also consider that once an attacker has made off with your data-store, even if it is currently infeasible to brute-force the secrets, there may be other ways around obtaining the missing pieces of information they need. Think about the paper shredders and the associated competitions. With patience, most puzzles can be cracked. If the compromise is an opportunistic type of attack, they will most likely just give up and seek an easier target. If it is a targeted attack by determined and experienced attackers, they will probably try other attack vectors until they get what they want.

Do not let over confidence be your weakness. An attacker will search out the weak link. Do your best to remove weak links.

Costs and Trade-offs

There is potential for hidden costs here, as adjacent layers will need to be hardened. There could be trade-offs here that force us to focus on the adjacent layers. This is never a bad thing though. It helps us to step back and take a holistic view of our security.

Store Configuration in Configuration files

There should be little cost in moving secrets out of source code and into configuration files.

Windows

You will need to weigh up whether the effort to obfuscate secrets is worth it or not. It can also make the developers job more cumbersome. Some of the options provided may be worthwhile doing.

Linux

Containers have many other advantages and you may already be using them for making your deployment processes easier and less likely to have dependency issues. They also help with scaling and load balancing, so they have multiple benefits.

Least Privilege

Is something you should be at least considering and probably doing in every case. It is one of those considerations that is worth while applying to most layers.

Location

Segmenting of resources is a common and effective measure to take for at least slowing down attacks and a cost well worth considering if you have not already.

Data-store Compromise

The countermeasures discussed here go without saying, although many organisations do not do them well if at all. It is up to you whether you want to be one of the statistics that has all of their secrets revealed. Following the countermeasures here is something that just needs to be done if you have any data that is sensitive in your data-store(s).

Advertisements

GnuPG Key-Pair with Sub-Keys

January 31, 2015

There are quite a few other posts on this topic, but my set-up hasn’t been exactly the same as any I found, so I found myself using quite a few resources to achieve exactly what I wanted.

Synopsis

For my personal work, I mostly use GNU/Linux distributions. All of the following operations have been carried out on such platforms and should work on any Debian derivative.

The initial set-up was performed on a machine other than a laptop. Then I discuss the process I took to get my key pairs into a laptop environment.

All keys are created using the RSA cryptosystem.

I’m going to create a large (4096 bit) RSA key-pair as my master (often called primary) key and then create a smaller (2048 bit) key-pair for signing and then another (2048 bit) key-pair for encrypting/decrypting.

Most of the work is done on the command line.

If you haven’t already got gnupg installed (accessed by the gpg command), run the following command as root. More than likely it’s already installed by default though:

apt-get install gnupg

Run gpg from command line. If it’s the first time it’s been run it’ll produce output like the following. This initialises your .gnupg directory and configuration:

gpg: directory `/home/<you>/.gnupg' created
gpg: new configuration file `/home/<you>/.gnupg/gpg.conf' created
gpg: WARNING: options in `/home/<you>/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/home/<you>/.gnupg/secring.gpg' created
gpg: keyring `/home/<you>/.gnupg/pubring.gpg' created
gpg: Go ahead and type your message ...

Just press Ctrl+d to terminate gpg.

Use the sks key-server pool

This section is optional apart from the first three lines that need to be added to the ~/.gnupg/gpg.conf file. The step of using the pool over TLS can of course be done later.

Rather than rely on a single specific key-server and also over an encrypted channel by using the hkps protocol. If a single server is not functioning properly it’s automatically removed from the pool.

In order to use the hkps protocol (hkp over TLS):

sudo apt-get install gnupg-curl

Now you will have a ~/.gnupg/gpg.conf file you can add the following lines to the end of the config file (SHA-1 (the default) is no longer considered secure).

personal-digest-preferences SHA512
cert-digest-algo SHA512
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
keyid-format 0xlong
with-fingerprint

There may be a keyserver and keyserver-options option in the ~/.gnupg/gpg.conf already. If so, modify it, if not, add it.

keyserver hkps://hkps.pool.sks-keyservers.net
keyserver-options ca-cert-file=/home/kim/.gnupg/sks-keyservers.netCA.pem

This assumes you downloaded the sks-keyservers.net CA certificate and put it in ~/.gnupg/ . You can of course put it anywhere, but the keyserver-options path will need to reflect your placement.

Verify the certificate’s fingerprint. Compare the fingerprint from the previous link with the output from the following command. It should be the same:

openssl x509 -in sks-keyservers.netCA.pem -fingerprint -noout

Anywhere below where the --keyserver option is specified, can be omitted if you’ve set-up the key-server pool.

Master Key-Pair Generation

This process will create a master key-pair that can be used for signing and a sub key-pair for encrypting/decrypting. We’re actually only going to use the master key-pair that’s created out of this process and we won’t use it for anything other than simply being a master, creating other key-pairs with it, signing other peoples keys etc. We won’t be using it for signing, encrypting/decrypting. We will create two additional sub-keys for this purpose in a bit.

This allows us to remove the master key from our computer and put it in a safe place (disconnected entirely from the network) that can’t be easily accessed. This means that if any of our computers are compromised, the attacker only gets access to our sub-keys which are the keys we use to actually do our day to day work of signing, encrypting outgoing messages and decrypting incoming messages.

On top of this they also need our pass phrase in order to compromise our identity. If in fact an attacker is able to compromise this as well, then we bring our master key out of hiding and can easily revoke the compromised sub key-pair(s) of which the public part is probably on a key-server or your blog or website. This way, when ever anyone gets your public sub-keys from one of the many key-servers or your blog or website, they will see that the public key(s) have been compromised and thus deprecated.

Now run:

gpg --gen-key

Output:

gpg (GnuPG) 1.4.16; Copyright (C) 2013 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?

I chose 1. That’s (1) RSA and RSA (default)

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)

Now because this is the master and we’re not actually going to be using it for signing our own messages and encrypting/decrypting and in theory we’ll probably just keep extending it’s expiry date indefinitely, we make it 4096 bit. Why? Because hardware is getting faster all the time and at some stage 2048 bit keys will not be large enough for cryptographic security. Why would we keep extending the master key-pair expiry date? Because we’ve worked hard to acquire other peoples trust (signatures of it) and we don’t really want to go through all that again. That’s why I’ve decided to not actually use the master for day to day work and do everything in my power to make sure it’s never compromised. If somehow the master key-pair was compromised, then I’d still have a revocation certificate that I could use to revoke it. It’d just be a pain though. I go through the creation of the revocation certificate for the master key-pair below.

4096 # Use smaller for sub-keys, as we can replace them easily when it becomes easier to crack them.
Requested keysize is 4096 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)

I chose 5y

Because I want my master key to expire eventually if it’s compromised along with the pass-phrase and somehow I lost the multiple copies of the master revocation certificate. If it never gets compromised, I’ll just keep extending the expiry date.

Key expires at Fri 06 Dec 2019 23:32:56 NZDT
Is this correct? (y/N)

I chose:

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:

Enter your real name:

Kim Carter
Email address:

Enter your email address:

First.Last@provider.com
Comment:

Here you can enter something like your website address or your on-line handle or what ever is useful for providing some more identification

lethalduck
You selected this USER-ID:
    "Kim Carter (lethalduck) <First.Last@provider.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?

Enter ‘O’ to continue:

O

Now you’re asked for a passphrase. Make this long and hard to guess. I don’t remember this myself. That’s why I use a password vault. To have unique credentials for everything.

You need a Passphrase to protect your secret key.

This is not my passphrase, but it’s a good example of one. Adding the extra characters that are all the same actually makes for a much harder to crack code. Oh, you’ll be prompted to enter this twice.

....................MW$]T&LP[=:[f/8=RQQ0M!++kMreX"....................

Now you’re asked to generate the entropy. This is done by interacting with the computer. keystrokes, mouse movements, storage media work. I find running my rsync scripts now is quite effective.

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.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 187 more bytes)

I added a pass phrase and waited for the entropy to be collected.
Once gpg has enough entropy, your key-pairs (master for signing, sub-key for encrypting/decrypting) will be created.

gpg: /home/kim/.gnupg/trustdb.gpg: trustdb created
gpg: key F90A5A4E 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 2019-12-06
pub 4096R/F90A5A4E 2014-12-07 [expires: 2019-12-06]
Key fingerprint = D6B6 1E46 4DC9 A3E9 F450 F7F8 C9FA 6F23 F90A 5A4E
uid Kim Carter (lethalduck) <First.Last@provider.com>
sub 4096R/65CA12E5 2014-12-07 [expires: 2019-12-06]

Add photo to a uid

Now I wanted to add a photo to my master key-pair.
PGP specifies that the image be no grater than 120×144. GPG recommends it be 240×288. So I chose the smaller size and reduced the quality as much as possible. Could only get it down to 10kb before the image became unrecognisable.

gpg --edit-key F90A5A4E
# or safer...
gpg --edit-key '<your fingerprint>'
# Don't know your fingerprint?
gpg --list-keys
gpg (GnuPG) 1.4.16; Copyright (C) 2013 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  4096R/F90A5A4E  created: 2014-12-07  expires: 2019-12-06  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/65CA12E5  created: 2014-12-07  expires: 2019-12-06  usage: E
[ultimate] (1). Kim Carter (lethalduck) <First.Last@provider.com>

gpg>

To add a jpeg:

addphoto

gpg complained that my 10kb image was very large, so I ditched adding the photo.

Add a sub-key for signing

Now before we go any further I just want to make note of the prefixes and suffixes that you’ll often encounter with gpg commands.

Listing your keys with

gpg -K # list secret keys

or

gpg -k # list public keys

will show the following prefixes for your keys.

sec === (sec)ret key
ssb === (s)ecret (s)u(b)-key
pub === (pub)lic key
sub === public (sub)-key

Roles of the key-pair will be represented by the middle character below.

Constant Character Explanation
PUBKEY_USAGE_SIG S Key is good for signing
PUBKEY_USAGE_CERT C Key is good for certifying other signatures
PUBKEY_USAGE_ENC E Key is good for encryption
PUBKEY_USAGE_AUTH A Key is good for authentication

When we add sub-keys, they are bound to the master key. The master key is modified to reference the sub-keys

What we want to do is add a sub-key for signing so we can move the master key-pair off of the machine and into a safe place.
We also want to change the expiry date and reduce the size to 2048 of both the new signing sub-key and also create another sub-key for encryption with a shorter expiry date.

Create backup of your ~/.gnupg directory:

umask 077; tar -cf $HOME/gnupg-backup.tar -C $HOME .gnupg

To add a signing sub-key:

gpg --edit-key F90A5A4E
# or safer...
gpg --edit-key '<your fingerprint>'
# Don't know your fingerprint?
gpg --list-keys

Output:

gpg (GnuPG) 1.4.16; Copyright (C) 2013 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  4096R/F90A5A4E  created: 2014-12-07  expires: 2019-12-06  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/65CA12E5  created: 2014-12-07  expires: 2019-12-06  usage: E
[ultimate] (1). Kim Carter (lethalduck) <First.Last@provider.com>

gpg>

Now we add the key

addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "Kim Carter (lethalduck) <First.Last@provider.com>"
4096-bit RSA key, ID F90A5A4E, created 2014-12-07

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
Your selection?

Now we want (4) RSA (sign only)

4

Output:

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)

Choose 2048 because we can easily regenerate this key-pair or extend the expiry date and at this stage 2048 is secure enough.

2048

Output:

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)

I set this to 2y

Key expires at Wed 07 Dec 2016 01:21:11 NZDT
Is this correct? (y/N)

y

Really create? (y/N)

y

After this gpg collects more entropy. When it’s done it dumps you back to the gpg prompt

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.

Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 186 more bytes)
.......+++++
.+++++

pub  4096R/F90A5A4E  created: 2014-12-07  expires: 2019-12-06  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/65CA12E5  created: 2014-12-07  expires: 2019-12-06  usage: E
sub  2048R/7A3122BD  created: 2014-12-07  expires: 2016-12-06  usage: S
[ultimate] (1). Kim Carter (lethalduck) <First.Last@provider.com>

gpg>

Now you can see from the ‘S’ suffix that we do now have a sub-key that’s “good for signing”

Same again but for encrypting

While still at the gpg prompt, run addkey again but choose option 6.

That’s (6) RSA (encrypt only)
Choose 2048 for the keysize.
Choose 2y (two years) for how long the key is valid for.

Eventually you’ll see:

pub  4096R/F90A5A4E  created: 2014-12-07  expires: 2019-12-06  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/65CA12E5  created: 2014-12-07  expires: 2019-12-06  usage: E
sub  2048R/7A3122BD  created: 2014-12-07  expires: 2016-12-06  usage: S
sub  2048R/8FF9669C  created: 2014-12-07  expires: 2016-12-06  usage: E
[ultimate] (1). Kim Carter (lethalduck) <First.Last@provider.com>

gpg>

Now you can see from the ‘E’ suffix that we do now have a sub-key that’s “good for encryption”

To save the new keys before finishing with gpg, type save.

Create Revocation Certificate for Master Key

gpg --output F90A5A4E.gpg-revocation-certificate --gen-revoke F90A5A4E

Output:

sec  4096R/F90A5A4E 2014-12-07 Kim Carter (lethalduck) <First.Last@provider.com>

Create a revocation certificate for this key? (y/N)

Type 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?

Type 1

Enter an optional description; end it with an empty line:
>

Enter anything you like here.

This revocation certificate was generated when the key was created.
>
Reason for revocation: Key has been compromised
This revocation certificate was generated when the key was created.
Is this okay? (y/N)

y

Output:

You need a passphrase to unlock the secret key for
user: "Kim Carter (lethalduck) <First.Last@provider.com>"
4096-bit RSA key, ID F90A5A4E, created 2014-12-07

ASCII armored output forced.
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!

Now store your master key-pair revocation certificate somewhere off of the network. Preferably in more than one place also.

Copy ~/.gnupg to an external device (/media/) for safe keeping before we remove the master key-pair from your computer.

Remove master key

Following are the commands to do this.

gpg --export-secret-subkeys F90A5A4E > /media/<your encrypted USB device>/subkeys
gpg --delete-secret-key F90A5A4E

Output:

gpg (GnuPG) 1.4.16; Copyright (C) 2013 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  4096R/F90A5A4E 2014-12-07 Kim Carter (lethalduck) <First.Last@provider.com>

Delete this key from the keyring? (y/N)

Type y

This is a secret key! - really delete? (y/N)

Type y

gpg --import /media/<your encrypted USB device>/subkeys

Output:

gpg: key F90A5A4E: secret key imported
gpg: key F90A5A4E: "Kim Carter (lethalduck) <First.Last@provider.com>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

Now check to make sure that the master key-pair is no longer on your computer but is on your USB device:

gpg -K

Output:

sec#  4096R/F90A5A4E 2014-12-07 [expires: 2019-12-06]
uid                  Kim Carter (lethalduck) <First.Last@provider.com>
ssb   4096R/65CA12E5 2014-12-07
ssb   2048R/7A3122BD 2014-12-07
ssb   2048R/8FF9669C 2014-12-07
gpg --home=/media/<your encrypted USB device>/.gnupg/ -K

Output:

sec   4096R/F90A5A4E 2014-12-07 [expires: 2019-12-06]
uid                  Kim Carter (lethalduck) <First.Last@provider.com>
ssb   4096R/65CA12E5 2014-12-07
ssb   2048R/7A3122BD 2014-12-07
ssb   2048R/8FF9669C 2014-12-07

You can see that the first command shows sec#. This means there is no master key-pair in your ~/.gnupg/ directory.

Upload your Public Keys to KeyServer

Remember if you used a key-server pool, anywhere the --keyserver option is specified, can be omitted.

I’ve chosen https://pgp.mit.edu/
You can choose any public keyserver. They all communicate with each other and sync updates at least daily. You can also send more than one public key by adding additional Ids after the –send-keys.

gpg --keyserver hkp://pgp.mit.edu/ --send-keys F90A5A4E

Output:

gpg: sending key F90A5A4E to hkp server pgp.mit.edu

Download public keys from KeyServer

gpg --keyserver hkp://pgp.mit.edu/ --recv-keys <key id to receive and merge signatures>

A safer way to do this is to not just trust every key from a key-server, but rather to verify the key belongs to who you think it belongs to before you download and trust it. Try one at a time and use the fingerprint rather than just the short Id.

gpg --keyserver hkp://pgp.mit.edu/ --recv-key '<fingerprint>'

The single quotes are mandatory around the fingerprint. Double quotes will also work.

Refreshing local Keys from Key-Server

gpg --refresh-keys

Set-up the Laptop with your key-pairs

Copy the contents of the desktops ~/.gnupg/ to the laptops ~/.gnupg/ . I just used the same USB drive for this, but made sure I didn’t mix this .gnupg/ up with the one that had the master key. Then delete the copy without the master key once copied to save any confusion. Also keep in mind that when you delete files from a flash drive they are not actually deleted. That’s why it’s important to use an encrypted USB drive. Also keep it in a very safe place, make a copy of it and keep that off site in a very safe place also.

Make sure you check the permissions of the ~/.gnupg files you just copied to the laptop so that they are the same as the files crated with the gpg command.

Adding another E-Mail Address

Now it’s easier if you do this here in the sequence, but I didn’t think about it until after I’d uploaded the public keys. If you do want to add another uid once you’ve moved the master key, copied your master key’less sub-keys to your laptop, it just means you’ve got to operate on the master key that you moved into /media//.gnupg/, then copy the contents of /media//.gnupg/ back to ~/.gnupg/ on both your desktop and laptop machines not forgetting to change file permissions again, remove master key from ~/.gnupg/ and upload the modified public keys again.

This is how you would add the additional uid:

gpg --home=/media/<your encrypted USB device>/.gnupg --edit-key F90A5A4E
# or safer...
gpg --home=/media/<your encrypted USB device>/.gnupg --edit-key '<your fingerprint>'
# Don't know your fingerprint?
gpg --list-keys

Output:

gpg (GnuPG) 1.4.16; Copyright (C) 2013 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.

gpg: DBG: locking for `/media/<your encrypted USB device>/.gnupg/trustdb.gpg.lock' done via O_EXCL
pub  4096R/F90A5A4E  created: 2014-12-07  expires: 2019-12-06  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/65CA12E5  created: 2014-12-07  expires: 2019-12-06  usage: E
sub  2048R/7A3122BD  created: 2014-12-07  expires: 2016-12-06  usage: S
sub  2048R/8FF9669C  created: 2014-12-07  expires: 2016-12-06  usage: E
[ultimate] (1). Kim Carter (lethalduck) <First.Last@provider.com>

gpg>

Add the extra uid now:

adduid

Output:

Real name:

Enter your real name:

Kim Carter

Output:

Email address:

Enter the additional email address you want:

kim.carter@owasp.org

Output:

Comment:

Add the web page that adds some proof of identity:

https://www.owasp.org/index.php/New_Zealand

Output:

You selected this USER-ID:
    "Kim Carter (https://www.owasp.org/index.php/New_Zealand) <kim.carter@owasp.org>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?

Type O

Output:

You need a passphrase to unlock the secret key for
user: "Kim Carter (lethalduck) <First.Last@provider.com>"
4096-bit RSA key, ID F90A5A4E, created 2014-12-07

pub  4096R/F90A5A4E  created: 2014-12-07  expires: 2019-12-06  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/65CA12E5  created: 2014-12-07  expires: 2019-12-06  usage: E
sub  2048R/7A3122BD  created: 2014-12-07  expires: 2016-12-06  usage: S
sub  2048R/8FF9669C  created: 2014-12-07  expires: 2016-12-06  usage: E
[ultimate] (1)  Kim Carter (lethalduck) <First.Last@provider.com>
[ unknown] (2). Kim Carter (https://www.owasp.org/index.php/New_Zealand) <First.Last@owasp.org>

gpg>

Now we want the same trust level applied to the second uid as the existing:

trust

Output:

pub  4096R/F90A5A4E  created: 2014-12-07  expires: 2019-12-06  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/65CA12E5  created: 2014-12-07  expires: 2019-12-06  usage: E
sub  2048R/7A3122BD  created: 2014-12-07  expires: 2016-12-06  usage: S
sub  2048R/8FF9669C  created: 2014-12-07  expires: 2016-12-06  usage: E
[ultimate] (1)  Kim Carter (lethalduck) <First.Last@provider.com>
[ unknown] (2). Kim Carter (https://www.owasp.org/index.php/New_Zealand) <First.Last@owasp.org>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision?

Type 5

Output:

Do you really want to set this key to ultimate trust? (y/N)

Type y

Output

pub  4096R/F90A5A4E  created: 2014-12-07  expires: 2019-12-06  usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/65CA12E5  created: 2014-12-07  expires: 2019-12-06  usage: E
sub  2048R/7A3122BD  created: 2014-12-07  expires: 2016-12-06  usage: S
sub  2048R/8FF9669C  created: 2014-12-07  expires: 2016-12-06  usage: E
[ultimate] (1)  Kim Carter (lethalduck) <First.Last@provider.com>
[ unknown] (2). Kim Carter (https://www.owasp.org/index.php/New_Zealand) <First.Last@owasp.org>

gpg>

Don’t worry that it still looks like it’s unknown. Once you save and try to edit again, you’ll see the change has been saved.

If you want to make the uid that you’ve tentatively just added your primary, select it:

uid 2

issue the command:

primary

and finally save:

save

Sign Someone Else’s Public Key

You’re going to have to download, import the persons key into your ~/.gnupg/pubring.gpg

If you’ve got a key-server pool configured, you won’t need the --keyserver option.

gpg --recv-key '<fingerprint of public key you want to import>'
gpg --home=/media/<your encrypted USB device>/.gnupg/ --primary-keyring=~/.gnupg/pubring.gpg --sign-key '<fingerprint of public key you want to sign>'

There will be some other output here. I wasn’t actually asked which trust level I wanted to provide, so I carried out the following edit.

gpg --edit-key '<fingerprint of public key you want to sign>'

Output:

gpg (GnuPG) 1.4.16; Copyright (C) 2013 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  4096R/<id of public key you just signed>  created: 2014-05-09  expires: never       usage: SC
                               trust: unknown       validity: unknown
sub  4096R/<a sub-key>  created: 2014-05-09  expires: never       usage: E
sub  4096R/<another sub-key>  created: 2014-05-09  expires: 2019-05-08  usage: S
[ unknown] (1). <key holders name> (4096 bit key generated 9/5/2014) <e-mail1@gmail.com>
[ unknown] (2)  <key holders name> (Their key) <e-mail@somethingelse.com>
[ unknown] (3)  <key holders name> (Their Yahoo) <e-mail@yahoo.com>
[ unknown] (4)  <key holders name> (Their Other Email Account) <e-mail@whatever.org>

gpg>

Issue the trust command:

trust

Output:

pub  4096R/<id of public key you just signed>  created: 2014-05-09  expires: never       usage: SC
                               trust: unknown       validity: unknown
sub  4096R/<a sub-key>  created: 2014-05-09  expires: never       usage: E
sub  4096R/<another sub-key>  created: 2014-05-09  expires: 2019-05-08  usage: S
[ unknown] (1). <key holders name> (4096 bit key generated 9/5/2014) <e-mail1@gmail.com>
[ unknown] (2)  <key holders name> (Their key) <e-mail@somethingelse.com>
[ unknown] (3)  <key holders name> (Their Yahoo) <e-mail@yahoo.com>
[ unknown] (4)  <key holders name> (Their Other Email Account) <e-mail@whatever.org>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision?
3

Output:

pub  4096R/<id of public key you just signed>  created: 2014-05-09  expires: never       usage: SC
                               trust: marginal      validity: unknown
sub  4096R/<a sub-key>  created: 2014-05-09  expires: never       usage: E
sub  4096R/<another sub-key>  created: 2014-05-09  expires: 2019-05-08  usage: S
[ unknown] (1). <key holders name> (4096 bit key generated 9/5/2014) <e-mail1@gmail.com>
[ unknown] (2)  <key holders name> (Their key) <e-mail@somethingelse.com>
[ unknown] (3)  <key holders name> (Their Yahoo) <e-mail@yahoo.com>
[ unknown] (4)  <key holders name> (Their Other Email Account) <e-mail@whatever.org>
Please note that the shown key validity is not necessarily correct
unless you restart the program.

gpg>

Email the Signed Public-Key

In order to send an email with the freshly signed public-key, attach the file generated with the following command, encrypt and send the email to the owner of the public key specified by their uid. Details on how to encrypt the e-mail are specific to the e-mail client you choose to use.

gpg --armor --output <long id of receivers public key>.signed-by.0xc9fa6f23f90a5a4e --export '<fingerprint of public key you just signed>'

Upload the Signed Public-Key to a Key Server

 

gpg --send-key '<fingerprint of public key you just signed>'

Output:

gpg: sending key <long id of receivers public key> to hkps server hkps.pool.sks-keyservers.net

Verify to make sure you’re public domain signing is good.

Import Your Public-Key Signed by Someone Else

At some stage you may need to import a copy of your public-key in the form of a file that someone else has added their signature to

gpg --import ./0xC9FA6F23F90A5A4E.signed-by-<someone else's long id>.asc

Then view your new signatures:

gpg --list-sigs 0xC9FA6F23F90A5A4E

Then upload them again with --send-key
and pull them down to your other machines with --refresh-keys. You’ll also need to --recv-key their keys so that your key recognises who the signatories are. Or… just simply copy over your ~/.gnupg/ directory. Make sure to check your permissions before and after the copy though. We don’t want anyone other than you being able to read these files. Especially the secring.gpg and any pem certs you have.

Browser based E-Mail

Two browser extensions that look OK are:

  1. Mailvelope for Firefox and Chrome (I’m using this)
    Getting set-up details
    Details of how this works here
  2. Mymail-Crypt for Gmail

Desktop based E-Mail

Thunderbird with enigmail

I also found that to send or reply to someone and encrypt, that I had to make a change in Thunderbird, as Thunderbird wrongly thinks I’m not trusting identities when I have specifically set trust levels. I’ve heard comments that if you set the trust level in gpg to “I trust ultimately” then Enigmail is happy to send your mail. I only trust myself ultimately so I found another way.
If you go into the Edit menu of Thunderbird -> Account Settings. For each email account in your gpg signature… OpenPGP Security -> Enigmail Preferences… -> Change “To send encrypted, accept” from Only trusted keys to “All usable keys”. Then when you get the final confirmation of sending encrypted email, you are asked to confirm the 8 digit ID. I just double check by

gpg --edit-key '<keyID that Thunderbird says it's using>'

Additional Resources I’ve Collected

Posts/articles, Documentation

Podcasts