diff --git a/.travis.yml b/.travis.yml
index c89bcf1275e2744b794041c2dc87af431cf3c95e..ef3ec362c418273bfcd84b2985e7563002fabd26 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -71,12 +71,14 @@ addons:
       - gfortran
       - mercurial
       - graphviz
+      - gnupg2
 
 # Work around Travis's lack of support for Python on OSX
 before_install:
   - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
   - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew ls --versions python > /dev/null || brew install python; fi
   - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew ls --versions gcc    > /dev/null || brew install gcc;    fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew ls --versions gnupg2 > /dev/null || brew install gnupg2; fi
   - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then virtualenv venv; fi
   - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then source venv/bin/activate; fi
 
diff --git a/lib/spack/docs/basic_usage.rst b/lib/spack/docs/basic_usage.rst
index f25247579b10966400d6aaceea73c1abba117ccb..6eba26a4b5b249e575ad162baaa38d03991b90a6 100644
--- a/lib/spack/docs/basic_usage.rst
+++ b/lib/spack/docs/basic_usage.rst
@@ -276,6 +276,70 @@ Seeing installed packages
 We know that ``spack list`` shows you the names of available packages,
 but how do you figure out which are already installed?
 
+.. _cmd-spack-gpg:
+
+^^^^^^^^^^^^^
+``spack gpg``
+^^^^^^^^^^^^^
+
+Spack has support for signing and verifying packages using GPG keys. A
+separate keyring is used for Spack, so any keys available in the user's home
+directory are not used.
+
+^^^^^^^^^^^^^^^^^^
+``spack gpg init``
+^^^^^^^^^^^^^^^^^^
+
+When Spack is first installed, its keyring is empty. Keys stored in
+:file:`var/spack/gpg` are the default keys for a Spack installation. These
+keys may be imported by running ``spack gpg init``. This will import the
+default keys into the keyring as trusted keys.
+
+-------------
+Trusting keys
+-------------
+
+Additional keys may be added to the keyring using
+``spack gpg trust <keyfile>``. Once a key is trusted, packages signed by the
+owner of they key may be installed.
+
+-------------
+Creating keys
+-------------
+
+You may also create your own key so that you may sign your own packages using
+``spack gpg create <name> <email>``. By default, the key has no expiration,
+but it may be set with the ``--expires <date>`` flag (see the ``gnupg2``
+documentation for accepted date formats). It is also recommended to add a
+comment as to the use of the key using the ``--comment <comment>`` flag. The
+public half of the key can also be exported for sharing with others so that
+they may use packages you have signed using the ``--export <keyfile>`` flag.
+Secret keys may also be later exported using the
+``spack gpg export <location> [<key>...]`` command.
+
+------------
+Listing keys
+------------
+
+In order to list the keys available in the keyring, the
+``spack gpg list`` command will list trusted keys with the ``--trusted`` flag
+and keys available for signing using ``--signing``. If you would like to
+remove keys from your keyring, ``spack gpg untrust <keyid>``. Key IDs can be
+email addresses, names, or (best) fingerprints.
+
+------------------------------
+Signing and Verifying Packages
+------------------------------
+
+In order to sign a package, ``spack gpg sign <file>`` should be used. By
+default, the signature will be written to ``<file>.asc``, but that may be
+changed by using the ``--output <file>`` flag. If there is only one signing
+key available, it will be used, but if there is more than one, the key to use
+must be specified using the ``--key <keyid>`` flag. The ``--clearsign`` flag
+may also be used to create a signed file which contains the contents, but it
+is not recommended. Signed packages may be verified by using
+``spack gpg verify <file>``.
+
 .. _cmd-spack-find:
 
 ^^^^^^^^^^^^^^
diff --git a/lib/spack/docs/getting_started.rst b/lib/spack/docs/getting_started.rst
index 971d42cea08836f849e0d6fe65ee37fe0a6c513b..75c2f662b5b8a81aa39c2fc1df8a9168c3c520ff 100644
--- a/lib/spack/docs/getting_started.rst
+++ b/lib/spack/docs/getting_started.rst
@@ -14,6 +14,7 @@ before Spack is run:
 1. Python 2 (2.6 or 2.7) or 3 (3.3 - 3.6)
 2. A C/C++ compiler
 3. The ``git`` and ``curl`` commands.
+4. If using the ``gpg`` subcommand, ``gnupg2`` is required.
 
 These requirements can be easily installed on most modern Linux systems;
 on Macintosh, XCode is required.  Spack is designed to run on HPC
diff --git a/lib/spack/spack/__init__.py b/lib/spack/spack/__init__.py
index 27283d10a96851720dabd8277669d4240bc687c1..057c54d665011e784e3368bf29f1d003b76d55ef 100644
--- a/lib/spack/spack/__init__.py
+++ b/lib/spack/spack/__init__.py
@@ -68,6 +68,13 @@
 etc_path       = join_path(prefix, "etc")
 
 
+# GPG paths.
+gpg_keys_path      = join_path(var_path, "gpg")
+mock_gpg_data_path = join_path(var_path, "gpg.mock", "data")
+mock_gpg_keys_path = join_path(var_path, "gpg.mock", "keys")
+gpg_path           = join_path(opt_path, "spack", "gpg")
+
+
 #-----------------------------------------------------------------------------
 # Initial imports (only for use in this file -- see __all__ below.)
 #-----------------------------------------------------------------------------
diff --git a/lib/spack/spack/cmd/gpg.py b/lib/spack/spack/cmd/gpg.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff511b652082a11f06b9ff59d8e5a95d2c4593a9
--- /dev/null
+++ b/lib/spack/spack/cmd/gpg.py
@@ -0,0 +1,168 @@
+##############################################################################
+# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##############################################################################
+from spack.util.gpg import Gpg
+import spack
+import os
+
+description = "handle GPG actions for spack"
+section = "developer"
+level = "long"
+
+
+def setup_parser(subparser):
+    setup_parser.parser = subparser
+    subparsers = subparser.add_subparsers(help='GPG sub-commands')
+
+    verify = subparsers.add_parser('verify')
+    verify.add_argument('package', type=str,
+                        help='the package to verify')
+    verify.add_argument('signature', type=str, nargs='?',
+                        help='the signature file')
+    verify.set_defaults(func=gpg_verify)
+
+    trust = subparsers.add_parser('trust')
+    trust.add_argument('keyfile', type=str,
+                       help='add a key to the trust store')
+    trust.set_defaults(func=gpg_trust)
+
+    untrust = subparsers.add_parser('untrust')
+    untrust.add_argument('--signing', action='store_true',
+                         help='allow untrusting signing keys')
+    untrust.add_argument('keys', nargs='+', type=str,
+                         help='remove keys from the trust store')
+    untrust.set_defaults(func=gpg_untrust)
+
+    sign = subparsers.add_parser('sign')
+    sign.add_argument('--output', metavar='DEST', type=str,
+                      help='the directory to place signatures')
+    sign.add_argument('--key', metavar='KEY', type=str,
+                      help='the key to use for signing')
+    sign.add_argument('--clearsign', action='store_true',
+                      help='if specified, create a clearsign signature')
+    sign.add_argument('package', type=str,
+                      help='the package to sign')
+    sign.set_defaults(func=gpg_sign)
+
+    create = subparsers.add_parser('create')
+    create.add_argument('name', type=str,
+                        help='the name to use for the new key')
+    create.add_argument('email', type=str,
+                        help='the email address to use for the new key')
+    create.add_argument('--comment', metavar='COMMENT', type=str,
+                        default='GPG created for Spack',
+                        help='a description for the intended use of the key')
+    create.add_argument('--expires', metavar='EXPIRATION', type=str,
+                        default='0', help='when the key should expire')
+    create.add_argument('--export', metavar='DEST', type=str,
+                        help='export the public key to a file')
+    create.set_defaults(func=gpg_create)
+
+    list = subparsers.add_parser('list')
+    list.add_argument('--trusted', action='store_true',
+                      help='list trusted keys')
+    list.add_argument('--signing', action='store_true',
+                      help='list keys which may be used for signing')
+    list.set_defaults(func=gpg_list)
+
+    init = subparsers.add_parser('init')
+    init.set_defaults(func=gpg_init)
+    init.set_defaults(import_dir=spack.gpg_keys_path)
+
+    export = subparsers.add_parser('export')
+    export.add_argument('location', type=str,
+                        help='where to export keys')
+    export.add_argument('keys', nargs='*',
+                        help='the keys to export; '
+                             'all secret keys if unspecified')
+    export.set_defaults(func=gpg_export)
+
+
+def gpg_create(args):
+    if args.export:
+        old_sec_keys = Gpg.signing_keys()
+    Gpg.create(name=args.name, email=args.email,
+               comment=args.comment, expires=args.expires)
+    if args.export:
+        new_sec_keys = set(Gpg.signing_keys())
+        new_keys = new_sec_keys.difference(old_sec_keys)
+        Gpg.export_keys(args.export, *new_keys)
+
+
+def gpg_export(args):
+    keys = args.keys
+    if not keys:
+        keys = Gpg.signing_keys()
+    Gpg.export_keys(args.location, *keys)
+
+
+def gpg_list(args):
+    Gpg.list(args.trusted, args.signing)
+
+
+def gpg_sign(args):
+    key = args.key
+    if key is None:
+        keys = Gpg.signing_keys()
+        if len(keys) == 1:
+            key = keys[0]
+        elif not keys:
+            raise RuntimeError('no signing keys are available')
+        else:
+            raise RuntimeError('multiple signing keys are available; '
+                               'please choose one')
+    output = args.output
+    if not output:
+        output = args.package + '.asc'
+    # TODO: Support the package format Spack creates.
+    Gpg.sign(key, args.package, output, args.clearsign)
+
+
+def gpg_trust(args):
+    Gpg.trust(args.keyfile)
+
+
+def gpg_init(args):
+    for root, _, filenames in os.walk(args.import_dir):
+        for filename in filenames:
+            if not filename.endswith('.key'):
+                continue
+            Gpg.trust(os.path.join(root, filename))
+
+
+def gpg_untrust(args):
+    Gpg.untrust(args.signing, *args.keys)
+
+
+def gpg_verify(args):
+    # TODO: Support the package format Spack creates.
+    signature = args.signature
+    if signature is None:
+        signature = args.package + '.asc'
+    Gpg.verify(signature, args.package)
+
+
+def gpg(parser, args):
+    if args.func:
+        args.func(args)
diff --git a/lib/spack/spack/test/cmd/gpg.py b/lib/spack/spack/test/cmd/gpg.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc6d57d91e3a4da11ee006b1b721e1faf0892591
--- /dev/null
+++ b/lib/spack/spack/test/cmd/gpg.py
@@ -0,0 +1,181 @@
+##############################################################################
+# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##############################################################################
+import argparse
+import os.path
+
+import pytest
+import spack
+import spack.cmd.gpg as gpg
+import spack.util.gpg as gpg_util
+from spack.util.executable import ProcessError
+
+
+@pytest.fixture(scope='function')
+def testing_gpg_directory(tmpdir):
+    old_gpg_path = gpg_util.GNUPGHOME
+    gpg_util.GNUPGHOME = str(tmpdir.join('gpg'))
+    yield
+    gpg_util.GNUPGHOME = old_gpg_path
+
+
+def has_gnupg2():
+    try:
+        gpg_util.Gpg.gpg()('--version')
+        return True
+    except Exception:
+        return False
+
+
+@pytest.mark.usefixtures('testing_gpg_directory')
+@pytest.mark.skipif(not has_gnupg2(),
+                    reason='These tests require gnupg2')
+def test_gpg(tmpdir):
+    parser = argparse.ArgumentParser()
+    gpg.setup_parser(parser)
+
+    # Verify a file with an empty keyring.
+    args = parser.parse_args(['verify', os.path.join(
+        spack.mock_gpg_data_path, 'content.txt')])
+    with pytest.raises(ProcessError):
+        gpg.gpg(parser, args)
+
+    # Import the default key.
+    args = parser.parse_args(['init'])
+    args.import_dir = spack.mock_gpg_keys_path
+    gpg.gpg(parser, args)
+
+    # List the keys.
+    # TODO: Test the output here.
+    args = parser.parse_args(['list', '--trusted'])
+    gpg.gpg(parser, args)
+    args = parser.parse_args(['list', '--signing'])
+    gpg.gpg(parser, args)
+
+    # Verify the file now that the key has been trusted.
+    args = parser.parse_args(['verify', os.path.join(
+        spack.mock_gpg_data_path, 'content.txt')])
+    gpg.gpg(parser, args)
+
+    # Untrust the default key.
+    args = parser.parse_args(['untrust', 'Spack testing'])
+    gpg.gpg(parser, args)
+
+    # Now that the key is untrusted, verification should fail.
+    args = parser.parse_args(['verify', os.path.join(
+        spack.mock_gpg_data_path, 'content.txt')])
+    with pytest.raises(ProcessError):
+        gpg.gpg(parser, args)
+
+    # Create a file to test signing.
+    test_path = tmpdir.join('to-sign.txt')
+    with open(str(test_path), 'w+') as fout:
+        fout.write('Test content for signing.\n')
+
+    # Signing without a private key should fail.
+    args = parser.parse_args(['sign', str(test_path)])
+    with pytest.raises(RuntimeError) as exc_info:
+        gpg.gpg(parser, args)
+    assert exc_info.value.args[0] == 'no signing keys are available'
+
+    # Create a key for use in the tests.
+    keypath = tmpdir.join('testing-1.key')
+    args = parser.parse_args(['create',
+                              '--comment', 'Spack testing key',
+                              '--export', str(keypath),
+                              'Spack testing 1',
+                              'spack@googlegroups.com'])
+    gpg.gpg(parser, args)
+    keyfp = gpg_util.Gpg.signing_keys()[0]
+
+    # List the keys.
+    # TODO: Test the output here.
+    args = parser.parse_args(['list', '--trusted'])
+    gpg.gpg(parser, args)
+    args = parser.parse_args(['list', '--signing'])
+    gpg.gpg(parser, args)
+
+    # Signing with the default (only) key.
+    args = parser.parse_args(['sign', str(test_path)])
+    gpg.gpg(parser, args)
+
+    # Verify the file we just verified.
+    args = parser.parse_args(['verify', str(test_path)])
+    gpg.gpg(parser, args)
+
+    # Export the key for future use.
+    export_path = tmpdir.join('export.testing.key')
+    args = parser.parse_args(['export', str(export_path)])
+    gpg.gpg(parser, args)
+
+    # Create a second key for use in the tests.
+    args = parser.parse_args(['create',
+                              '--comment', 'Spack testing key',
+                              'Spack testing 2',
+                              'spack@googlegroups.com'])
+    gpg.gpg(parser, args)
+
+    # List the keys.
+    # TODO: Test the output here.
+    args = parser.parse_args(['list', '--trusted'])
+    gpg.gpg(parser, args)
+    args = parser.parse_args(['list', '--signing'])
+    gpg.gpg(parser, args)
+
+    test_path = tmpdir.join('to-sign-2.txt')
+    with open(str(test_path), 'w+') as fout:
+        fout.write('Test content for signing.\n')
+
+    # Signing with multiple signing keys is ambiguous.
+    args = parser.parse_args(['sign', str(test_path)])
+    with pytest.raises(RuntimeError) as exc_info:
+        gpg.gpg(parser, args)
+    assert exc_info.value.args[0] == \
+        'multiple signing keys are available; please choose one'
+
+    # Signing with a specified key.
+    args = parser.parse_args(['sign', '--key', keyfp, str(test_path)])
+    gpg.gpg(parser, args)
+
+    # Untrusting signing keys needs a flag.
+    args = parser.parse_args(['untrust', 'Spack testing 1'])
+    with pytest.raises(ProcessError):
+        gpg.gpg(parser, args)
+
+    # Untrust the key we created.
+    args = parser.parse_args(['untrust', '--signing', keyfp])
+    gpg.gpg(parser, args)
+
+    # Verification should now fail.
+    args = parser.parse_args(['verify', str(test_path)])
+    with pytest.raises(ProcessError):
+        gpg.gpg(parser, args)
+
+    # Trust the exported key.
+    args = parser.parse_args(['trust', str(export_path)])
+    gpg.gpg(parser, args)
+
+    # Verification should now succeed again.
+    args = parser.parse_args(['verify', str(test_path)])
+    gpg.gpg(parser, args)
diff --git a/lib/spack/spack/util/gpg.py b/lib/spack/spack/util/gpg.py
new file mode 100644
index 0000000000000000000000000000000000000000..ccaf33519b8b562132e0910dec4a5457d368466e
--- /dev/null
+++ b/lib/spack/spack/util/gpg.py
@@ -0,0 +1,120 @@
+##############################################################################
+# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##############################################################################
+
+import os
+
+import spack
+from spack.util.executable import Executable
+
+
+GNUPGHOME = spack.gpg_path
+
+
+class Gpg(object):
+    @staticmethod
+    def gpg():
+        # TODO: Support loading up a GPG environment from a built gpg.
+        gpg = Executable('gpg2')
+        if not os.path.exists(GNUPGHOME):
+            os.makedirs(GNUPGHOME)
+            os.chmod(GNUPGHOME, 0o700)
+        gpg.add_default_env('GNUPGHOME', GNUPGHOME)
+        return gpg
+
+    @classmethod
+    def create(cls, **kwargs):
+        r, w = os.pipe()
+        r = os.fdopen(r, 'r')
+        w = os.fdopen(w, 'w')
+        w.write('''
+        Key-Type: rsa
+        Key-Length: 4096
+        Key-Usage: sign
+        Name-Real: %(name)s
+        Name-Email: %(email)s
+        Name-Comment: %(comment)s
+        Expire-Date: %(expires)s
+        %%no-protection
+        %%commit
+        ''' % kwargs)
+        w.close()
+        cls.gpg()('--gen-key', '--batch', input=r)
+        r.close()
+
+    @classmethod
+    def signing_keys(cls):
+        keys = []
+        output = cls.gpg()('--list-secret-keys', '--with-colons',
+                           '--fingerprint', output=str)
+        for line in output.split('\n'):
+            if line.startswith('fpr'):
+                keys.append(line.split(':')[9])
+        return keys
+
+    @classmethod
+    def export_keys(cls, location, *keys):
+        cls.gpg()('--armor', '--export', '--output', location, *keys)
+
+    @classmethod
+    def trust(cls, keyfile):
+        cls.gpg()('--import', keyfile)
+
+    @classmethod
+    def untrust(cls, signing, *keys):
+        args = [
+            '--yes',
+            '--batch',
+        ]
+        if signing:
+            signing_args = args + ['--delete-secret-keys'] + list(keys)
+            cls.gpg()(*signing_args)
+        args.append('--delete-keys')
+        args.extend(keys)
+        cls.gpg()(*args)
+
+    @classmethod
+    def sign(cls, key, file, output, clearsign=False):
+        args = [
+            '--armor',
+            '--default-key', key,
+            '--output', output,
+            file,
+        ]
+        if clearsign:
+            args.insert(0, '--clearsign')
+        else:
+            args.insert(0, '--detach-sign')
+        cls.gpg()(*args)
+
+    @classmethod
+    def verify(cls, signature, file):
+        cls.gpg()('--verify', signature, file)
+
+    @classmethod
+    def list(cls, trusted, signing):
+        if trusted:
+            cls.gpg()('--list-public-keys')
+        if signing:
+            cls.gpg()('--list-secret-keys')
diff --git a/var/spack/gpg.mock/README.md b/var/spack/gpg.mock/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..95215a863477fe549a5f96c8b5cb101b693e8d67
--- /dev/null
+++ b/var/spack/gpg.mock/README.md
@@ -0,0 +1,3 @@
+# Mock GPG directory
+
+This directory contains keys and data used in the testing Spack.
diff --git a/var/spack/gpg.mock/data/content.txt b/var/spack/gpg.mock/data/content.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6ab0f567cfbd190b820195c414aeceb563c3e76b
--- /dev/null
+++ b/var/spack/gpg.mock/data/content.txt
@@ -0,0 +1 @@
+This file has a signature signed by an external key.
diff --git a/var/spack/gpg.mock/data/content.txt.asc b/var/spack/gpg.mock/data/content.txt.asc
new file mode 100644
index 0000000000000000000000000000000000000000..7593156113363db27ee78bc1817d53e170b3819b
--- /dev/null
+++ b/var/spack/gpg.mock/data/content.txt.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iQIcBAABCAAGBQJZELiKAAoJENygJBhApdriPvgP/0shBTmx4jg6QaI0zyie8a+R
++L/o9iIV4MqvBI5g+Ti+nktoCSxSOPOYFW4af740A7/43wIML9LK+gIhx/QbCrMb
+bNqzyIry9/L6PK1cCuXvd10CT+MCF1P0hdaMtKihdBYB3J8f5y1i30z+a8YWsRsX
+tPMVF/HunlpAkSWIpjmbJzFPT1R/UiBHl4VJ+mM3NNZYNIq8ZhKUiXwlQkZ8R8zg
+M0IEFkwfFtp7JxnhG7jR0k63cNm3KSocAJpwENy46RKGsAvwvqTzRh4T2MlmQIjH
+TC1MA8alJvtSdBHpkKffSU8jLewKHe1H48nc9NifMy04Ni8fSlGZe14Oe7Krqla0
+qWs+XHrGCmSleyiRUQes1MKQ7NhumKEoEaU+q0/c+lUDILZp1TlfvTPg2fzng4M/
+YF6+f+wqM+xY6z1/IloOMHis5oALjARSO88ldrLU4DQp/6jTKJO/+I4uWhMnPkMW
++a3GLWl1CShReHKbWZTLFtdQATZXA8M6wQ8FAsLOmRLb0AlEQ28A8fHrBCCdU2xj
+tSG++U1ZUo64cMYQmIMsvIApnkTh7qCkDjaVBP1to3qc83YHncxorydz9ERpuDvP
+d1IOHlJyUSM4+sLkCPvH9QyTaJn/x7D/VraznEiptGON7G6G9AgyAzIgYamm1Kwh
+UDhbQDFDhLLvUSDGzO3l
+=kwo9
+-----END PGP SIGNATURE-----
diff --git a/var/spack/gpg.mock/keys/external.key b/var/spack/gpg.mock/keys/external.key
new file mode 100644
index 0000000000000000000000000000000000000000..d08c90ea7f3d6eb558cca09d16f4c5816d72bb61
--- /dev/null
+++ b/var/spack/gpg.mock/keys/external.key
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQINBFkQuFIBEAC7DiUM7jQ01kaGX+4nguzVeYquBRYoEUiObl5UIVSavMn4I7Oy
+aytG+qR26tUpunjEB6ftIQMJSyPKueclUJBaQ9lzQ3WpFC3ItpBNkMxHpiqPa9DX
+ddMk2QtJt4TlCWJEdnhR/92mMF+vf7B5/OvFvKOi0P+AwzBHC8IKTxml/UosmeVI
+Cs69FzRDXyqQxQAkATmuDmHXPaC6RkDmpVRe3ej+Kr+Xu4vcb/EBHg/vcZkFdSmi
+hyOj21/8LQZzcwTg4TSgHzKqbjPtIEQM3NNksvcFYlq2X0ad4cBcxa1Hj5xV8oS/
+bdYOFSdsh3QRROcEeKYVQZhvCR12qS93P4b2egbamBxCQK0Sn6QPIjlR6+Ya2/6p
+/hHddF+YVA6HJ22QZjaORf9lImYfYMs1ka2GtgkczOeaFEfcJ96nIa8Qb1jcrOon
+/3k/l+Ae09HRCcGB2DgKXw7S+CXKt46Oadp3bIDAyceotGnrG3cVA6A9Lwqy6U/5
+ywry8ETu3wlIR3EAIwM0a/3xCPg3cC/bt9rSqsFcmXyxltGI2CBTWcTqcyjW4VAw
+nVI8otBd4yNdimhpxLfx6AaMjA+D+OSltnAZUrp1fSFVhWLpTxLbcTv+HJ/g4U+x
++PAsQ79Hzmzvy/8nOvIprGzY4LCmBPbLUB47Yu761HhYQhkuJiYP1R/GzQARAQAB
+tDpTcGFjayB0ZXN0aW5nIChTcGFjayB0ZXN0aW5nIGtleSkgPHNwYWNrQGdvb2ds
+ZWdyb3Vwcy5jb20+iQI3BBMBCAAhBQJZELhSAhsDBQsJCAcCBhUICQoLAgQWAgMB
+Ah4BAheAAAoJENygJBhApdriOnUP/iLC1ZxyBP3STSVgBBTS1L6FnRAc9ya6eXNT
+EwLLoSL0I0srs0sThmhyW38ZamsXYDhggaetShxemcO0BoNAii/oNK9yQoXNF4f6
+7wg2ZxCDuDjp/3VsbiI+kNlH2kj1tQ/M53ak9nYhmwLJFfKzjQBWJiyTwYZwO3MB
+QvXBvLIKj6IDS20o+7jbOq8F243vo5/uNHc/6C9eC3i4jzXWVlln2+iN/e5sVt+X
+ZiggLK2Goj5CZ7ZjZQvdoH4wKbSPLBg0Lh5FYSih9p0wx0UTEoi0jPqFUDw81duz
+IyxjbGASSaUxoz16C2U/olPEAAXeBe4266jRQwTrn+sEIX5FD+RGoryXQ97pV5up
+I9wb2anVAMHOf20iYep3vYTjnFG/81ykODm8+I4D/Jj0EEe1E2b0D+7RQ9xKNYxC
+fDgY3isXBFzmS6O4h8N27P06yfzQX+zvjPrrHRB7ka2pmDT3M421p2wN0n9aCq1J
+8+M5UdpF98A38oosyE53KcItoCUFLgEP3KrWPwvpDUC2sNQAOFiHeitzc+v1iwmD
+RScdefCQ8qc2JJdCqMG6M0tlFy6Tw1o0eBYOhhDGa0rq/PQ4NewR2dj+yDXXBGJy
+ElR0VChqniMCyd2Q4SDPnhcVrWPTYSKL1MpsL0lXED8TGOdoAHHmQNU8MWhqmdBy
+zcWArNUY
+=yVqw
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/var/spack/gpg/README.md b/var/spack/gpg/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..122d24f84126b414acd6ae10f98a9687a30f31f7
--- /dev/null
+++ b/var/spack/gpg/README.md
@@ -0,0 +1,5 @@
+# GPG Keys
+
+This directory contains keys that should be trusted by this installation of
+Spack.  They are imported when running `spack gpg init`, but may also be
+imported manually with `spack gpg trust path/to/key`.