{"id":650,"date":"2018-05-12T08:40:27","date_gmt":"2018-05-12T06:40:27","guid":{"rendered":"https:\/\/blogs.gentoo.org\/mgorny\/?p=650"},"modified":"2018-08-13T18:00:16","modified_gmt":"2018-08-13T16:00:16","slug":"on-openpgp-gnupg-key-management","status":"publish","type":"post","link":"https:\/\/blogs.gentoo.org\/mgorny\/2018\/05\/12\/on-openpgp-gnupg-key-management\/","title":{"rendered":"On\u00a0OpenPGP (GnuPG) key management"},"content":{"rendered":"<p>Over the\u00a0time, a\u00a0number of\u00a0developers have had problems following the\u00a0Gentoo OpenPGP key policy (<a rel=\"external\" href=\"https:\/\/www.gentoo.org\/glep\/glep-0063.html\">GLEP\u00a063<\/a>.  In\u00a0particular, the\u00a0key expiration requirements have resulted in\u00a0many developers wanting to replace their key unnecessarily.  I&#8217;ve been asked to write some instructions on\u00a0managing your OpenPGP key, and\u00a0I&#8217;ve decided to go for a\u00a0full blog post with some less-known tips.  I\u00a0won&#8217;t be getting into detailed explanations how to use GnuPG though \u2014 you may still need to read the\u00a0documentation after all.<\/p>\n<p><!--more--><\/p>\n<h2>Primary key and subkeys<\/h2>\n<p>An\u00a0OpenPGP key actually consists of\u00a0one or\u00a0more pairs of public and\u00a0private keys \u2014 the\u00a0<em>primary key<\/em> (or\u00a0<em>root key<\/em>, in\u00a0GLEP\u00a063 naming), and\u00a0zero or\u00a0more <em>subkeys<\/em>.  Ideally, the\u00a0primary key is only used to create subkeys, UIDs, manipulate them and\u00a0sign other people&#8217;s keys.  All \u2018non-key\u2019 cryptographic operations are done using subkeys.  This reduces the\u00a0wear of the\u00a0primary key, and\u00a0the\u00a0risk of it being compromised.<\/p>\n<p>If\u00a0you don&#8217;t use a\u00a0smartcard, then a\u00a0good idea would be to move the\u00a0private part of\u00a0primary key off-site since you don&#8217;t need it for normal operation.  However, before doing that please remember to always have a\u00a0<em>revocation certificate<\/em> around.  You will need it to\u00a0revoke the\u00a0primary key if\u00a0you lose it.  With GnuPG\u00a02.1, removing private keys is trivial.  First, list all keys with <em>keygrips<\/em>:<\/p>\n<pre><kbd>$ gpg --list-secret --with-keygrip<\/kbd>\n<samp>\/home\/you\/.gnupg\/pubring.kbx\n-------------------------------\nsec   rsa2048\/0xBBC7E6E002FE74E8 2018-05-12 [SC] [expires: 2020-05-11]\n      55642983197252C35550375FBBC7E6E002FE74E8\n      Keygrip = B51708C7209017A162BDA515A9803D3089B993F0\nuid                   [ultimate] Example key \nssb   rsa2048\/0xB7BA421CDCD4AF16 2018-05-12 [E] [expires: 2020-05-11]\n      Keygrip = 92230550DA684B506FC277B005CD3296CB70463C<\/samp><\/pre>\n<p>Note that the\u00a0output may differ depending on\u00a0your settings.  The\u00a0<samp>sec<\/samp> entry indicates a\u00a0primary key.  Once you find the\u00a0correct key, just look for a\u00a0file named after its <samp>Keygrip<\/samp> in\u00a0<kbd>~\/.gnupg\/private-keys-v1.d<\/kbd> (e.g. <kbd>B51708C7209017A162BDA515A9803D3089B993F0.key<\/kbd> here).  Move that file off-site and\u00a0voil\u00e0!<\/p>\n<p>In\u00a0fact, you can go even further and\u00a0use a\u00a0dedicated off-line system to create and\u00a0manage keys, and\u00a0only transfer appropriate private keys (and\u00a0public keyring updates) to your online hosts.  You can transfer and\u00a0remove any other private key the\u00a0same way, and\u00a0use <kbd>--export-key<\/kbd> to transfer the\u00a0public keys.<\/p>\n<h2>How many subkeys to use?<\/h2>\n<p>Create at\u00a0least one <em>signing<\/em> subkey and\u00a0exactly one <em>encryption<\/em> subkey.<\/p>\n<p><em>Signing keys<\/em> are used to sign data, i.e. to prove its integrity and\u00a0authenticity.  Using multiple signing subkeys is rather trivial \u2014 you can explicitly specify the\u00a0key to use while creating a\u00a0signature (note that you need to append <kbd>!<\/kbd> to key-id to force non-default subkey), and\u00a0GnuPG will automatically use the\u00a0correct subkey when verifying the\u00a0signature.  To reduce the\u00a0wear of your main signing subkey, you can create a\u00a0separate signing subkey for Gentoo commits.  Or you can go ever further, and\u00a0have a\u00a0separate signing subkey for each machine you&#8217;re using (and\u00a0keep only the\u00a0appropriate key on\u00a0each machine).<\/p>\n<p><em>Encryption keys<\/em> are used to encrypt messages.  While technically it is possible to have multiple encryption subkeys, GnuPG does not make that meaningful.  When someone will try to encrypt a\u00a0message to you, it will insist on\u00a0using the\u00a0newest key even if multiple keys are valid.  Therefore, use only one encryption key to avoid confusion.<\/p>\n<p>There is also a\u00a0third key class: <em>authentication keys<\/em> that can be used in\u00a0place of\u00a0SSH keys.  If you intend to use them, I suggest the\u00a0same rule as\u00a0for SSH keys, that is one key for\u00a0each host holding the\u00a0keyring.  More on\u00a0using GnuPG for SSH below.<\/p>\n<p>To\u00a0summarize: use one encryption subkey, and\u00a0as\u00a0many signing and\u00a0authentication subkeys as\u00a0you need.  Using more subkeys reduces individual wear of\u00a0each key, and\u00a0makes it easier to assess the\u00a0damage if one of\u00a0them gets compromised.<\/p>\n<h2>When to create a\u00a0new key?<\/h2>\n<p>One of\u00a0the\u00a0common misconceptions is that you need to create a\u00a0new key when the\u00a0current one expires.  This is not really the\u00a0purpose of\u00a0key expiration \u2014 we use it mostly to automatically rule out dead keys.  There are generally three cases when you want to create a\u00a0new key:<\/p>\n<ol>\n<li>if the key is compromised,<\/li>\n<li>if the\u00a0primary key is irrecoverably lost,<\/li>\n<li>if the\u00a0key uses really weak algorithm (e.g. short DSA key).<\/li>\n<\/ol>\n<p>Most of\u00a0the\u00a0time, you will just decide to prolong the\u00a0primary key and\u00a0subkeys, i.e.\u00a0use the\u00a0<kbd>--edit-key<\/kbd> option to update their expiration dates.  Note that GnuPG is not very user-friendly there.  To prolong the\u00a0primary key, use <kbd>expire<\/kbd> command without any\u00a0subkeys selected.  To prolong one or\u00a0more subkeys, select them using <kbd>key<\/kbd> and\u00a0then use <kbd>expire<\/kbd>.  Normally, you will want to do this periodically, <em>before<\/em> the\u00a0expiration date to give people some time to\u00a0refresh.  Add it to your calendar as a\u00a0periodic event.<\/p>\n<pre>$ <kbd>gpg --edit-key 0xBBC7E6E002FE74E8<\/kbd>\n<samp>Secret key is available.\n\nsec  rsa2048\/0xBBC7E6E002FE74E8\n     created: 2018-05-12  expires: 2020-05-11  usage: SC  \n     trust: ultimate      validity: ultimate\nssb  rsa2048\/0xB7BA421CDCD4AF16\n     created: 2018-05-12  expires: 2020-05-11  usage: E   \n[ultimate] (1). Example key &lt;example@example.com&gt;\n\ngpg&gt;<\/samp> <kbd>expire<\/kbd>\n<samp>Changing expiration time for the primary key.\nPlease specify how long the key should be valid.\n         0 = key does not expire\n      &lt;n&gt;  = key expires in n days\n      &lt;n&gt;w = key expires in n weeks\n      &lt;n&gt;m = key expires in n months\n      &lt;n&gt;y = key expires in n years\nKey is valid for? (0)<\/samp> <kbd>3y<\/kbd>\n<samp>Key expires at Tue May 11 12:32:35 2021 CEST\nIs this correct? (y\/N)<\/samp> <kbd>y<\/kbd>\n\n<samp>sec  rsa2048\/0xBBC7E6E002FE74E8\n     created: 2018-05-12  expires: 2021-05-11  usage: SC  \n     trust: ultimate      validity: ultimate\nssb  rsa2048\/0xB7BA421CDCD4AF16\n     created: 2018-05-12  expires: 2020-05-11  usage: E   \n[ultimate] (1). Example key &lt;example@example.com&gt;\n\ngpg&gt;<\/samp> <kbd>key 1<\/kbd>\n\n<samp>sec  rsa2048\/0xBBC7E6E002FE74E8\n     created: 2018-05-12  expires: 2021-05-11  usage: SC  \n     trust: ultimate      validity: ultimate\nssb* rsa2048\/0xB7BA421CDCD4AF16\n     created: 2018-05-12  expires: 2020-05-11  usage: E   \n[ultimate] (1). Example key &lt;example@example.com&gt;\n\ngpg&gt;<\/samp> <kbd>expire<\/kbd>\n<samp>Changing expiration time for a subkey.\nPlease specify how long the key should be valid.\n         0 = key does not expire\n      &lt;n&gt;  = key expires in n days\n      &lt;n&gt;w = key expires in n weeks\n      &lt;n&gt;m = key expires in n months\n      &lt;n&gt;y = key expires in n years\nKey is valid for? (0)<\/samp> <kbd>1y<\/kbd>\n<samp>Key expires at Sun May 12 12:32:47 2019 CEST\nIs this correct? (y\/N)<\/samp> <kbd>y<\/kbd>\n\n<samp>sec  rsa2048\/0xBBC7E6E002FE74E8\n     created: 2018-05-12  expires: 2021-05-11  usage: SC  \n     trust: ultimate      validity: ultimate\nssb* rsa2048\/0xB7BA421CDCD4AF16\n     created: 2018-05-12  expires: 2019-05-12  usage: E   \n[ultimate] (1). Example key &lt;example@example.com&gt;<\/samp><\/pre>\n<p>If\u00a0one of the\u00a0conditions above applies to one of\u00a0your subkeys, or you think that it has reached a\u00a0very high wear, you will want to replace the\u00a0subkey.  While at\u00a0it, make sure that the\u00a0old key is\u00a0either expired or\u00a0revoked (but don&#8217;t revoke the\u00a0whole key accidentally!).  If one of\u00a0those conditions applies to your primary key, revoke it and\u00a0start propagating your new key.<\/p>\n<p>Please remember to upload your key to key servers after each change (using <kbd>--send-keys<\/kbd>).<\/p>\n<p>To summarize: prolong your keys periodically, rotate subkeys whenever you consider that beneficial but avoid replacing the\u00a0primary key unless really necessary.<\/p>\n<h2>Using gpg-agent for SSH authentication<\/h2>\n<p>If you already have to set up a\u00a0secure store for OpenPGP keys, why not use it for\u00a0SSH keys as\u00a0well?  GnuPG provides ssh-agent emulation which lets you use an\u00a0OpenPGP subkey to authenticate via SSH.<\/p>\n<p>Firstly, you need to create a\u00a0new key.  You need to use the\u00a0<kbd>--expert<\/kbd> option to\u00a0access additional options.  Use <kbd>addkey<\/kbd> to\u00a0create a\u00a0new key, choose one of\u00a0the\u00a0options with custom capabilities and\u00a0toggle them from the\u00a0default <em>sign<\/em>+&lt;em&lt;encrypt<\/em> to\u00a0<em>authenticate<\/em>:<\/p>\n<pre><kbd>$ gpg --expert --edit-key 0xBBC7E6E002FE74E8<\/kbd>\n<samp>Secret key is available.\n\nsec  rsa2048\/0xBBC7E6E002FE74E8\n     created: 2018-05-12  expires: 2020-05-11  usage: SC  \n     trust: ultimate      validity: ultimate\nssb  rsa2048\/0xB7BA421CDCD4AF16\n     created: 2018-05-12  expires: 2020-05-11  usage: E   \n[ultimate] (1). Example key &lt;example@example.com&gt;\n\ngpg&gt;<\/samp> <kbd>addkey<\/kbd>\n<samp>Please select what kind of key you want:\n   (3) DSA (sign only)\n   (4) RSA (sign only)\n   (5) Elgamal (encrypt only)\n   (6) RSA (encrypt only)\n   (7) DSA (set your own capabilities)\n   (8) RSA (set your own capabilities)\n  (10) ECC (sign only)\n  (11) ECC (set your own capabilities)\n  (12) ECC (encrypt only)\n  (13) Existing key\nYour selection?<\/samp> <kbd>8<\/kbd>\n\n<samp>Possible actions for a RSA key: Sign Encrypt Authenticate \nCurrent allowed actions: Sign Encrypt \n\n   (S) Toggle the sign capability\n   (E) Toggle the encrypt capability\n   (A) Toggle the authenticate capability\n   (Q) Finished\n\nYour selection?<\/samp> <kbd>s<\/kbd>\n\n<samp>Possible actions for a RSA key: Sign Encrypt Authenticate \nCurrent allowed actions: Encrypt \n\n   (S) Toggle the sign capability\n   (E) Toggle the encrypt capability\n   (A) Toggle the authenticate capability\n   (Q) Finished\n\nYour selection?<\/samp> <kbd>e<\/kbd>\n\n<samp>Possible actions for a RSA key: Sign Encrypt Authenticate \nCurrent allowed actions: \n\n   (S) Toggle the sign capability\n   (E) Toggle the encrypt capability\n   (A) Toggle the authenticate capability\n   (Q) Finished\n\nYour selection?<\/samp> <kbd>a<\/kbd>\n\n<samp>Possible actions for a RSA key: Sign Encrypt Authenticate \nCurrent allowed actions: Authenticate \n\n   (S) Toggle the sign capability\n   (E) Toggle the encrypt capability\n   (A) Toggle the authenticate capability\n   (Q) Finished\n\nYour selection?<\/samp> <kbd>q<\/kbd>\n[...]<\/pre>\n<p>Once the key is created, find its keygrip:<\/p>\n<pre>$ <kbd>gpg --list-secret --with-keygrip<\/kbd>\n<samp>\/home\/mgorny\/.gnupg\/pubring.kbx\n-------------------------------\nsec   rsa2048\/0xBBC7E6E002FE74E8 2018-05-12 [SC] [expires: 2020-05-11]\n      55642983197252C35550375FBBC7E6E002FE74E8\n      Keygrip = B51708C7209017A162BDA515A9803D3089B993F0\nuid                   [ultimate] Example key &lt;example@example.com&gt;\nssb   rsa2048\/0xB7BA421CDCD4AF16 2018-05-12 [E] [expires: 2020-05-11]\n      Keygrip = 92230550DA684B506FC277B005CD3296CB70463C\nssb   rsa2048\/0x2BE2AF20C43617A0 2018-05-12 [A] [expires: 2018-05-13]\n      Keygrip = 569A0C016AB264B0451309775FDCF06A2DE73473<\/samp><\/pre>\n<p>This time we&#8217;re talking about the\u00a0keygrip of the\u00a0<samp>[A]<\/samp> key.  Append that to\u00a0<kbd>~\/.gnupg\/sshcontrol<\/kbd>:<\/p>\n<pre>$ <kbd>echo 569A0C016AB264B0451309775FDCF06A2DE73473 &gt;&gt; ~\/.gnupg\/sshcontrol<\/kbd><\/pre>\n<p>The\u00a0final step is to have gpg-agent with <kbd>--enable-ssh-support<\/kbd> started.  The\u00a0exact procedure here depends on\u00a0the\u00a0environment used.  In\u00a0XFCE, it involves setting a\u00a0hidden configuration option:<\/p>\n<pre>$ <kbd>xfconf-query -c xfce4-session -p \/startup\/ssh-agent\/type -n -t string -s gpg-agent<\/kbd><\/pre>\n<h2>Further reading<\/h2>\n<ul>\n<li><a rel=\"external\" href=\"https:\/\/www.gentoo.org\/glep\/glep-0063.html\">GLEP 63: Gentoo GPG key policies<\/a><\/li>\n<li><a rel=\"external\" href=\"https:\/\/wiki.debian.org\/Subkeys\">Subkeys &#8211; Debian Wiki<\/a><\/li>\n<li><a rel=\"external\" href=\"https:\/\/docs.xfce.org\/xfce\/xfce4-session\/advanced#ssh_and_gpg_agents\">xfce \u00bb xfce4-session \u00bb advanced # SSH and GPG Agents<\/a><\/li>\n<li><a rel=\"external\" href=\"https:\/\/wiki.archlinux.org\/index.php\/GnuPG#SSH_agent\">GnuPG &#8211; ArchWiki # SSH agent<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Over the\u00a0time, a\u00a0number of\u00a0developers have had problems following the\u00a0Gentoo OpenPGP key policy (GLEP\u00a063. In\u00a0particular, the\u00a0key expiration requirements have resulted in\u00a0many developers wanting to replace their key unnecessarily. I&#8217;ve been asked to write some instructions on\u00a0managing your OpenPGP key, and\u00a0I&#8217;ve decided to go for a\u00a0full blog post with some less-known tips. I\u00a0won&#8217;t be getting into detailed &hellip; <a href=\"https:\/\/blogs.gentoo.org\/mgorny\/2018\/05\/12\/on-openpgp-gnupg-key-management\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;On\u00a0OpenPGP (GnuPG) key management&#8221;<\/span><\/a><\/p>\n","protected":false},"author":137,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[10],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/650"}],"collection":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/users\/137"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/comments?post=650"}],"version-history":[{"count":25,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/650\/revisions"}],"predecessor-version":[{"id":676,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/650\/revisions\/676"}],"wp:attachment":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/media?parent=650"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/categories?post=650"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/tags?post=650"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}