git.schokokeks.org
Repositories
Help
Report an Issue
derivepassphrase.git
Code
Commits
Branches
Tags
Suche
Strukturansicht:
1bff169
Branches
Tags
documentation-tree
master
wishlist
0.1.0
0.1.1
0.1.2
0.1.3
0.2.0
0.3.0
0.3.1
0.3.2
0.3.3
0.4.0
0.5
0.5.1
0.5.2
0.6
derivepassphrase.git
0.x
reference
prerequisites-ssh-key
index.html
Deployed 4d028b5c74e3 to 0.x with MkDocs 1.6.1 and mike 2.1.4
Marco Ricci
commited
1bff169
at 2026-04-04 13:59:04
index.html
Blame
History
Raw
<!doctype html> <html lang="en" class="no-js"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="description" content="An almost faithful Python reimplementation of James Coglan's vault."> <meta name="author" content="Marco Ricci"> <link rel="canonical" href="https://the13thletter.info/derivepassphrase/0.x/reference/prerequisites-ssh-key/"> <link rel="prev" href="../derivepassphrase.vault/"> <link rel="next" href="../../explanation/"> <link rel="icon" href="../../assets/images/favicon.png"> <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.6"> <title>Using derivepassphrase vault with an SSH key - derivepassphrase</title> <link rel="stylesheet" href="../../assets/stylesheets/main.484c7ddc.min.css"> <style>:root{--md-text-font:"Noto Sans";--md-code-font:"Noto Mono"}</style> <link rel="stylesheet" href="../../assets/_mkdocstrings.css"> <link rel="stylesheet" href="../../mkdocstrings_recommended_styles.css"> <link rel="stylesheet" href="../../wishlist_styling.css"> </head> <body dir="ltr"> <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> <label class="md-overlay" for="__drawer"></label> <div data-md-component="skip"> <a href="#prerequisites-for-using-derivepassphrase-vault-with-an-ssh-key" class="md-skip"> Skip to content </a> </div> <div data-md-component="announce"> </div> <div data-md-color-scheme="default" data-md-component="outdated" hidden> </div> <div class="md-container" data-md-component="container"> <nav class="md-tabs" aria-label="Tabs" data-md-component="tabs"> <div class="md-grid"> <ul class="md-tabs__list"> <li class="md-tabs__item"> <a href="../.." class="md-tabs__link"> Overview </a> </li> <li class="md-tabs__item"> <a href="../../tutorials/" class="md-tabs__link"> Tutorials & Examples </a> </li> <li class="md-tabs__item"> <a href="../../how-tos/" class="md-tabs__link"> How-Tos </a> </li> <li class="md-tabs__item md-tabs__item--active"> <a href="../" class="md-tabs__link"> Reference </a> </li> <li class="md-tabs__item"> <a href="../../explanation/" class="md-tabs__link"> Design & Background </a> </li> <li class="md-tabs__item"> <a href="../../changelog/" class="md-tabs__link"> Changelog </a> </li> <li class="md-tabs__item"> <a href="../../wishlist/" class="md-tabs__link"> Wishlist </a> </li> </ul> </div> </nav> <main class="md-main" data-md-component="main"> <div class="md-main__inner md-grid"> <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" > <div class="md-sidebar__scrollwrap"> <div class="md-sidebar__inner"> <nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0"> <label class="md-nav__title" for="__drawer"> <a href="../.." title="derivepassphrase" class="md-nav__button md-logo" aria-label="derivepassphrase" data-md-component="logo"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> derivepassphrase </label> <div class="md-nav__source"> <a href="https://git.schokokeks.org/derivepassphrase.git" title="Go to repository" class="md-source" data-md-component="source"> <div class="md-source__icon md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg> </div> <div class="md-source__repository"> the-13th-letter/derivepassphrase </div> </a> </div> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../.." class="md-nav__link"> <span class="md-ellipsis"> Overview </span> </a> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" > <div class="md-nav__link md-nav__container"> <a href="../../tutorials/" class="md-nav__link "> <span class="md-ellipsis"> Tutorials & Examples </span> </a> <label class="md-nav__link " for="__nav_2" id="__nav_2_label" tabindex="0"> <span class="md-nav__icon md-icon"></span> </label> </div> <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false"> <label class="md-nav__title" for="__nav_2"> <span class="md-nav__icon md-icon"></span> Tutorials & Examples </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../tutorials/basic-setup-passphrase/" class="md-nav__link"> <span class="md-ellipsis"> Setting up derivepassphrase vault for three accounts, with a master passphrase </span> </a> </li> <li class="md-nav__item"> <a href="../../tutorials/basic-setup-ssh-key/" class="md-nav__link"> <span class="md-ellipsis"> Using a master SSH key with derivepassphrase vault on existing accounts </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" > <div class="md-nav__link md-nav__container"> <a href="../../how-tos/" class="md-nav__link "> <span class="md-ellipsis"> How-Tos </span> </a> <label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="0"> <span class="md-nav__icon md-icon"></span> </label> </div> <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false"> <label class="md-nav__title" for="__nav_3"> <span class="md-nav__icon md-icon"></span> How-Tos </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../how-tos/ssh-key/" class="md-nav__link"> <span class="md-ellipsis"> How to set up derivepassphrase vault with an SSH key </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" checked> <div class="md-nav__link md-nav__container"> <a href="../" class="md-nav__link "> <span class="md-ellipsis"> Reference </span> </a> <label class="md-nav__link " for="__nav_4" id="__nav_4_label" tabindex=""> <span class="md-nav__icon md-icon"></span> </label> </div> <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="true"> <label class="md-nav__title" for="__nav_4"> <span class="md-nav__icon md-icon"></span> Reference </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_2" > <label class="md-nav__link" for="__nav_4_2" id="__nav_4_2_label" tabindex=""> <span class="md-ellipsis"> Man pages </span> <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_2_label" aria-expanded="false"> <label class="md-nav__title" for="__nav_4_2"> <span class="md-nav__icon md-icon"></span> Man pages </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../derivepassphrase.1/" class="md-nav__link"> <span class="md-ellipsis"> derivepassphrase(1) </span> </a> </li> <li class="md-nav__item"> <a href="../derivepassphrase-vault.1/" class="md-nav__link"> <span class="md-ellipsis"> derivepassphrase-vault(1) </span> </a> </li> <li class="md-nav__item"> <a href="../derivepassphrase-export.1/" class="md-nav__link"> <span class="md-ellipsis"> derivepassphrase-export(1) </span> </a> </li> <li class="md-nav__item"> <a href="../derivepassphrase-export-vault.1/" class="md-nav__link"> <span class="md-ellipsis"> derivepassphrase-export-vault(1) </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_3" > <label class="md-nav__link" for="__nav_4_3" id="__nav_4_3_label" tabindex=""> <span class="md-ellipsis"> API docs: Module derivepassphrase </span> <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_3_label" aria-expanded="false"> <label class="md-nav__title" for="__nav_4_3"> <span class="md-nav__icon md-icon"></span> API docs: Module derivepassphrase </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../derivepassphrase.cli/" class="md-nav__link"> <span class="md-ellipsis"> Submodule cli </span> </a> </li> <li class="md-nav__item"> <a href="../derivepassphrase.exporter/" class="md-nav__link"> <span class="md-ellipsis"> Subpackage exporter </span> </a> </li> <li class="md-nav__item"> <a href="../derivepassphrase.sequin/" class="md-nav__link"> <span class="md-ellipsis"> Submodule sequin </span> </a> </li> <li class="md-nav__item"> <a href="../derivepassphrase.ssh_agent/" class="md-nav__link"> <span class="md-ellipsis"> Submodule ssh_agent </span> </a> </li> <li class="md-nav__item"> <a href="../derivepassphrase._types/" class="md-nav__link"> <span class="md-ellipsis"> Submodule _types </span> </a> </li> <li class="md-nav__item"> <a href="../derivepassphrase.vault/" class="md-nav__link"> <span class="md-ellipsis"> Submodule vault </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_4" checked> <label class="md-nav__link" for="__nav_4_4" id="__nav_4_4_label" tabindex=""> <span class="md-ellipsis"> Technical prerequisites </span> <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_4_label" aria-expanded="true"> <label class="md-nav__title" for="__nav_4_4"> <span class="md-nav__icon md-icon"></span> Technical prerequisites </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item md-nav__item--active"> <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc"> <label class="md-nav__link md-nav__link--active" for="__toc"> <span class="md-ellipsis"> Using derivepassphrase vault with an SSH key </span> <span class="md-nav__icon md-icon"></span> </label> <a href="./" class="md-nav__link md-nav__link--active"> <span class="md-ellipsis"> Using derivepassphrase vault with an SSH key </span> </a> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class="md-nav__title" for="__toc"> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> <li class="md-nav__item"> <a href="#ssh-agent" class="md-nav__link"> <span class="md-ellipsis"> A running SSH agent </span> </a> </li> <li class="md-nav__item"> <a href="#python-support" class="md-nav__link"> <span class="md-ellipsis"> A Python installation that can talk to the SSH agent </span> </a> </li> <li class="md-nav__item"> <a href="#ssh-key" class="md-nav__link"> <span class="md-ellipsis"> A supported SSH key </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" > <div class="md-nav__link md-nav__container"> <a href="../../explanation/" class="md-nav__link "> <span class="md-ellipsis"> Design & Background </span> </a> <label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="0"> <span class="md-nav__icon md-icon"></span> </label> </div> <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false"> <label class="md-nav__title" for="__nav_5"> <span class="md-nav__icon md-icon"></span> Design & Background </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../explanation/faq-altered-versions/" class="md-nav__link"> <span class="md-ellipsis"> "altered versions" license requirement </span> </a> </li> <li class="md-nav__item"> <a href="../../explanation/faq-vault-interchangable-passphrases/" class="md-nav__link"> <span class="md-ellipsis"> "interchangable passphrases" in vault </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" > <label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0"> <span class="md-ellipsis"> Changelog </span> <span class="md-nav__icon md-icon"></span> </label> <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false"> <label class="md-nav__title" for="__nav_6"> <span class="md-nav__icon md-icon"></span> Changelog </label> <ul class="md-nav__list" data-md-scrollfix> <li class="md-nav__item"> <a href="../../changelog/" class="md-nav__link"> <span class="md-ellipsis"> Changelog </span> </a> </li> <li class="md-nav__item"> <a href="../../upgrade-notes/" class="md-nav__link"> <span class="md-ellipsis"> Upgrade notes </span> </a> </li> <li class="md-nav__item"> <a href="../../pycompatibility/" class="md-nav__link"> <span class="md-ellipsis"> Python compatibility </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7" > <div class="md-nav__link md-nav__container"> <a href="../../wishlist/" class="md-nav__link "> <span class="md-ellipsis"> Wishlist </span> </a> </div> <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false"> <label class="md-nav__title" for="__nav_7"> <span class="md-nav__icon md-icon"></span> Wishlist </label> <ul class="md-nav__list" data-md-scrollfix> </ul> </nav> </li> </ul> </nav> </div> </div> </div> <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" > <div class="md-sidebar__scrollwrap"> <div class="md-sidebar__inner"> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class="md-nav__title" for="__toc"> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> <li class="md-nav__item"> <a href="#ssh-agent" class="md-nav__link"> <span class="md-ellipsis"> A running SSH agent </span> </a> </li> <li class="md-nav__item"> <a href="#python-support" class="md-nav__link"> <span class="md-ellipsis"> A Python installation that can talk to the SSH agent </span> </a> </li> <li class="md-nav__item"> <a href="#ssh-key" class="md-nav__link"> <span class="md-ellipsis"> A supported SSH key </span> </a> </li> </ul> </nav> </div> </div> </div> <div class="md-content" data-md-component="content"> <article class="md-content__inner md-typeset"> <a href="https://git.schokokeks.org/derivepassphrase.git/raw/master/docs/reference/prerequisites-ssh-key.md" title="View source of this page" class="md-content__button md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 18c.56 0 1 .44 1 1s-.44 1-1 1-1-.44-1-1 .44-1 1-1m0-3c-2.73 0-5.06 1.66-6 4 .94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4m0 6.5a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5M9.27 20H6V4h7v5h5v4.07c.7.08 1.36.25 2 .49V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4.5a8.2 8.2 0 0 1-1.23-2"/></svg> </a> <h1 id="prerequisites-for-using-derivepassphrase-vault-with-an-ssh-key">Prerequisites for using <code>derivepassphrase vault</code> with an SSH key<a class="headerlink" href="#prerequisites-for-using-derivepassphrase-vault-with-an-ssh-key" title="Permanent link">¶</a></h1> <p>Using <code>derivepassphrase vault</code> with an SSH key requires:</p> <ol> <li><a href="#ssh-agent">a running SSH agent</a>,</li> <li><a href="#python-support">a Python installation that can talk to the SSH agent</a>, and</li> <li><a href="#ssh-key">a supported SSH key.</a></li> </ol> <h3 id="ssh-agent">A running SSH agent<a class="headerlink" href="#ssh-agent" title="Permanent link">¶</a></h3> <p>SSH agents are usually packaged as part of SSH client distributions. Pageant from <a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/">PuTTY</a> is known to work, on both UNIX and Windows. <code>ssh-agent</code> from <a href="https://www.openssh.com/">OpenSSH</a> is known to work well on UNIX, and somewhat poorly on Windows; see notes below. <code>gpg-agent</code> (v2) from <a href="https://gnupg.org/">GnuPG</a> is also known to work, but comes with caveats; again, see notes below.</p> <p>If in doubt, we recommend OpenSSH on UNIX and Pageant on Windows, because they are the <i>de-facto</i> canonical SSH agent implementation on their respective operating system.</p> <div class="admonition note"> <p class="admonition-title">Agent-specific features</p> <ul> <li>OpenSSH’s <code>ssh-agent</code> supports limiting the time the agent holds the key in memory (“key lifetime”), on UNIX only. We recommend its usage.</li> <li><code>ssh-agent</code> and GnuPG’s <code>gpg-agent</code> support requiring confirmation upon each use for a specific key. (Again, for <code>ssh-agent</code> only on UNIX.) We recommend its usage as well.</li> </ul> </div> <section id="agent-specific-notes"> <div class="admonition note"> <p class="admonition-title">Other agent-specific notes</p> <div class="tabbed-set tabbed-alternate" data-tabs="1:2"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">OpenSSH on Windows</label><label for="__tabbed_1_2">GnuPG/<code>gpg-agent</code></label></div> <div class="tabbed-content"> <div class="tabbed-block"> <p>Using OpenSSH on Windows with <code>derivepassphrase vault</code> is possible, but currently <em>not recommended</em>. <a href="https://github.com/PowerShell/Win32-OpenSSH/issues/1056#issuecomment-362494167" title="Issue #1056: ssh-agent should support '-c' and '-t' options of ssh-add">The Windows port of OpenSSH lacks support for key constraints [1]</a> <a href="https://github.com/PowerShell/Win32-OpenSSH/issues/2314#issuecomment-2529160589" title="Issue #2314: Adding key with confirmation option to ssh-agent gives "agent refused operation"">[2]</a>, which are the main advantage OpenSSH has over Pageant. Without this functionality, Pageant is the better choice: more supported key formats, manually lockable and unlockable key material in the agent, and no Administrator credentials needed to configure the system.</p> <p>Additionally, the ported SSH agent implements the agent protocol incorrectly because it terminates the connection when encountering an unsupported request, instead of returning an error code. (The original agent, on UNIX, implements the protocol correctly.) This makes it difficult for <code>derivepassphrase vault</code> to correctly <em>detect</em> or <em>verify</em> that it is talking to the OpenSSH agent on Windows, instead of merely <em>assuming</em> it is doing so.</p> </div> <div class="tabbed-block"> <details class="info"> <summary>GnuPG terminology</summary> <dl> <dt>GnuPG home directory</dt> <dd>The directory where GnuPG keeps its configuration; defaults to <code>C:\​Users\​<username>\​AppData\​Roaming\​gnupg</code> on Windows and <code>~/​.gnupg</code> on POSIX. The user may set up multiple such directories. Agents are bound to a specific home directory; conversely, there can only be one agent per home directory.</dd> <dt>keygrip</dt> <dd>A GnuPG-specific fingerprint for cryptographic keys. Similar to the SSH key fingerprint, but not SSH-specific.</dd> <dt><code>sshcontrol</code></dt> <dd>A text file in the GnuPG home directory, listing the keygrips of SSH-compatible keys which <code>gpg-agent</code> knows about. <code>gpg-agent</code> will only advertise keys from this list if the corresponding private key is also known (on disk, on a smartcard, etc.).</dd> </dl> </details> <ul> <li> <p><code>gpg-agent</code> v2.0 and later uses a <em>persistent</em> database of known keys, SSH or otherwise. “Adding” a key to the agent actually means <em>importing</em> it, and requires choosing an “import passphrase” to protect the key on disk, in the persistent database. <code>gpg-agent</code> will cache the import passphrase in memory, and if that cache entry expires, then the <em>import passphrase</em> must be provided to unlock the key.</p> </li> <li> <p>The GnuPG distribution does not contain tools to generate native SSH keys or interactively add keys to a running <code>gpg-agent</code>, because its purpose is to expose keys in a different format (OpenPGP) to other (agent-compatible) SSH clients. A third-party tool (such as a full SSH client distribution) is necessary to load/import native SSH keys into <code>gpg-agent</code>.</p> </li> <li> <p>As a design consequence of the persistent database, <code>gpg-agent</code> always lists all known SSH keys as available in the agent. It is impossible to remove an SSH key from <code>gpg-agent</code> using standard SSH agent operations.</p> <details class="info"> <summary>Removing an SSH key from <code>gpg-agent</code> manually</summary> <p>The list of SSH-capable keys currently held by <code>gpg-agent</code> can be queried interactively with the <code>gpg-connect-agent</code> tool:</p> <div class="tabbed-set tabbed-alternate" data-tabs="2:2"><input checked="checked" id="__tabbed_2_1" name="__tabbed_2" type="radio" /><input id="__tabbed_2_2" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="__tabbed_2_1">SSH keys uploaded</label><label for="__tabbed_2_2">OpenPGP keys used as SSH keys</label></div> <div class="tabbed-content"> <div class="tabbed-block"> <div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1</span> <span class="normal">2</span> <span class="normal">3</span> <span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="gp">$ </span>gpg-connect-agent<span class="w"> </span><span class="s1">'KEYINFO --ssh-list --ssh-fpr=SHA256'</span><span class="w"> </span>/bye <span class="go">S KEYINFO 04779A9B67BC8930046D9ABA86F1F85E1957D593 D - - 1 C SHA256:0h+WAokssfhzfzVyuMLJlIcWyCtk5WiXI8BHyhXYxC0 - S</span> <span class="go">S KEYINFO 9233C66A7A62D5866493F613D5F2E1A24343E048 D - - 1 C SHA256:1OHE0HrVlaSzJn2aQXQIKRu0tfO1CEMefy95K2Bt0xA - S</span> <span class="go">OK</span> </code></pre></div></td></tr></table></div> </div> <div class="tabbed-block"> <div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1</span> <span class="normal">2</span> <span class="normal">3</span> <span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="gp">$ </span>gpg-connect-agent<span class="w"> </span><span class="s1">'KEYINFO --list --with-ssh --ssh-fpr=SHA256'</span><span class="w"> </span>/bye <span class="go">S KEYINFO 04779A9B67BC8930046D9ABA86F1F85E1957D593 D - - 1 C SHA256:0h+WAokssfhzfzVyuMLJlIcWyCtk5WiXI8BHyhXYxC0 - S</span> <span class="go">S KEYINFO 9233C66A7A62D5866493F613D5F2E1A24343E048 D - - 1 C SHA256:1OHE0HrVlaSzJn2aQXQIKRu0tfO1CEMefy95K2Bt0xA - S</span> <span class="go">OK</span> </code></pre></div></td></tr></table></div> </div> </div> </div> <p>The agent identifies cryptographic keys (of any kind) by the keygrip (the third entry on each line, so <code>04779A9B67BC8930046D9ABA86F1F85E1957D593</code> for the first key and <code>9233C66A7A62D5866493F613D5F2E1A24343E048</code> for the second key in the snippet above). By matching the SSH fingerprint (the ninth entry on each line), we can then determine the keygrip of the key we wish to remove from the agent:</p> <div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">6</span> <span class="normal">7</span> <span class="normal">8</span> <span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="go">> DELETE_KEY 04779A9B67BC8930046D9ABA86F1F85E1957D593</span> <span class="go">OK</span> <span class="go">> DELETE_KEY 9233C66A7A62D5866493F613D5F2E1A24343E048</span> <span class="go">OK</span> </code></pre></div></td></tr></table></div> <p>(The agent will prompt for confirmation.) We can then confirm that the key is no longer loaded because the fourth entry changes from <code>D</code> (“on disk”) to <code>-</code> (“missing”):</p> <div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">10</span> <span class="normal">11</span> <span class="normal">12</span> <span class="normal">13</span> <span class="normal">14</span> <span class="normal">15</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="go">> KEYINFO --ssh-list --ssh-fpr=SHA256</span> <span class="go">S KEYINFO 04779A9B67BC8930046D9ABA86F1F85E1957D593 - - - - - - - S</span> <span class="go">S KEYINFO 9233C66A7A62D5866493F613D5F2E1A24343E048 - - - - - - - S</span> <span class="go">OK</span> <span class="go">> BYE</span> <span class="go">OK closing connection</span> </code></pre></div></td></tr></table></div> <p>At this point, the keys are no longer available to the agent, but still “known” to the agent. To make <code>gpg-agent</code> “forget” them, the respective keygrip needs to be removed from <code>sshcontrol</code>.</p> </details> </li> <li> <p><code>gpg-agent</code> does not advertise its communication socket by default, contrary to other SSH agents, so it must be manually advertised:</p> <div class="tabbed-set tabbed-alternate" data-tabs="3:3"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><input id="__tabbed_3_3" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1">UNIX</label><label for="__tabbed_3_2">Windows (<code>libassuan</code> socket)</label><label for="__tabbed_3_3">Windows (OpenSSH emulation)</label></div> <div class="tabbed-content"> <div class="tabbed-block"> <div class="highlight"><pre><span></span><code><span class="gp">$ </span><span class="nv">SSH_AUTH_SOCK</span><span class="o">=</span><span class="s2">"</span><span class="k">$(</span>gpgconf<span class="w"> </span>--list-dirs<span class="w"> </span>agent-ssh-socket<span class="k">)</span><span class="s2">"</span> <span class="gp">$ </span><span class="nb">export</span><span class="w"> </span>SSH_AUTH_SOCK </code></pre></div> </div> <div class="tabbed-block"> <p><code>gpg-agent</code> on Windows contains a native emulation of UNIX domain sockets by the <code>assuan</code> library, which GnuPG internally uses for network connectivity and inter-process communication. No specific configuration is necessary, and the agent address can be directly obtained with <code>gpgconf</code>:</p> <div class="highlight"><pre><span></span><code><span class="gp">$ </span>gpgconf<span class="w"> </span>--list-dirs<span class="w"> </span>agent-ssh-socket </code></pre></div> <p>This mode, sadly, is not currently supported. The system is specific to GnuPG/<code>libassuan</code>, and unlikely to be deployed widely enough to make implementing this a priority for us… at least, relative to the other, more common interprocess communication channels for SSH agents on Windows.</p> </div> <div class="tabbed-block"> <p>From v2.4 onwards, <code>gpg-agent</code> supports masquerading as OpenSSH’s <code>ssh-agent</code> on Windows, by passing the <code>--enable-win32-openssh-support</code> command-line argument to the agent. (Because of <code>gpg-agent</code>’s idiosyncratic autostart behavior, it is usually simpler to add the corresponding option <code>enable-win32-openssh-support</code> to the <code>gpg-agent</code> configuration file instead.)</p> <p>This mode is fully supported, at least as of GnuPG version 2.4.8. Note, however, that <a href="https://dev.gnupg.org/T8013#210624">the GnuPG developers consider this communication endpoint support experimental and untested</a>,<sup id="fnref:gpg-agent-openssh-emulation-experimental"><a class="footnote-ref" href="#fn:gpg-agent-openssh-emulation-experimental">1</a></sup> so it is unclear if GnuPG will continue to provide this masquerading functionality.</p> </div> </div> </div> </li> </ul> </div> </div> </div> </div> </section> <h3 id="python-support">A Python installation that can talk to the SSH agent<a class="headerlink" href="#python-support" title="Permanent link">¶</a></h3> <p>On non-Windows operating systems, the SSH agent is expected to advertise its communication socket via the <code>SSH_AUTH_SOCK</code> environment variable, which is common procedure. Therefore, <a class="autorefs autorefs-external" href="https://docs.python.org/3/library/socket.html#socket.AF_UNIX">your Python installation must support UNIX domain sockets</a>.</p> <p>Since version 0.6, Windows is supported. <a class="autorefs autorefs-external" href="https://docs.python.org/3/library/ctypes.html#ctypes.WinDLL">Your Python installation must support interfacing with the Windows system DLLs.</a> By default, like on non-Windows systems, the SSH agent is expected to advertise its communication socket via the <code>SSH_AUTH_SOCK</code> environment variable. Alternatively, <code>derivepassphrase</code> can be configured to connect to the well-known socket addresses of Pageant or the OpenSSH agent instead.<sup id="fnref:pageant-socket-address"><a class="footnote-ref" href="#fn:pageant-socket-address">2</a></sup></p> <p><code>derivepassphrase vault --version</code> will report on supported and on unavailable features, including “master SSH key”:<sup id="fnref:feature-support"><a class="footnote-ref" href="#fn:feature-support">3</a></sup></p> <div class="tabbed-set tabbed-alternate" data-tabs="4:2"><input checked="checked" id="__tabbed_4_1" name="__tabbed_4" type="radio" /><input id="__tabbed_4_2" name="__tabbed_4" type="radio" /><div class="tabbed-labels"><label for="__tabbed_4_1">supported</label><label for="__tabbed_4_2">unavailable</label></div> <div class="tabbed-content"> <div class="tabbed-block"> <div class="highlight"><pre><span></span><code><span class="gp">$ </span>derivepassphrase<span class="w"> </span>vault<span class="w"> </span>--version <span class="go">derivepassphrase 0.5</span> <span class="go">Using cryptography 44.0.0</span> <span class="go">Using click 8.1.8</span> <span class="go">Supported features: master SSH key.</span> </code></pre></div> </div> <div class="tabbed-block"> <div class="highlight"><pre><span></span><code><span class="gp">$ </span>derivepassphrase<span class="w"> </span>vault<span class="w"> </span>--version <span class="go">derivepassphrase 0.5</span> <span class="go">Using cryptography 44.0.0</span> <span class="go">Using click 8.1.8</span> <span class="go">Unavailable features: master SSH key.</span> </code></pre></div> </div> </div> </div> <h3 id="ssh-key">A supported SSH key<a class="headerlink" href="#ssh-key" title="Permanent link">¶</a></h3> <p>For an SSH key to be usable by <code>derivepassphrase</code>, the SSH agent must always generate the same signature for the same input, i.e. the signature must be deterministic for this key type. Commonly used SSH key types (as of January 2026) include <a href="https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm">ECDSA</a>, <a href="https://en.wikipedia.org/wiki/EdDSA#Ed25519">Ed25519</a>, <a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)">RSA</a>, and, somewhat less commonly, <a href="https://en.wikipedia.org/wiki/EdDSA#Ed448">Ed448</a> and <a href="https://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>.</p> <ul> <li> <p>RSA, Ed25519 and Ed448 signatures are deterministic by definition. Thus RSA, Ed25519 and Ed448 keys are supported under any SSH agent that implements them.</p> </li> <li> <p>DSA and ECDSA signatures require choosing a value specific to each signature (a “cryptographic nonce”), which must be unpredictable. Typical DSA/ECDSA implementations therefore generate a suitably large random number as the nonce. This makes signatures non-deterministic, and thus unsuitable for <code>derivepassphrase</code>.</p> <details class="info"> <summary>Exception: PuTTY/Pageant and RFC 6979</summary> <p><a href="https://www.rfc-editor.org/rfc/rfc6979">RFC 6979</a> specifies a method to <em>calculate</em> the nonce from the DSA/ECDSA key and the message to be signed. DSA/ECDSA signatures from SSH agents implementing RFC 6979 are therefore deterministic, and thus <em>also</em> suitable for <code>derivepassphrase</code>. Pageant 0.81 implements RFC 6979.</p> <div class="admonition warning"> <p class="admonition-title">Warning: Pageant < 0.81</p> <p>Pageant 0.80 and earlier uses a different, homegrown method to calculate the nonce deterministically. Those versions are <em>also</em> prinicipally suitable for use with <code>derivepassphrase</code>, but <strong>they generate different signatures – and different derived passphrases – than Pageant 0.81 and later</strong>.</p> </div> </details> </li> </ul> <details class="info"> <summary>What SSH key type do I have?</summary> <p>If, according to your SSH agent, your key’s type…</p> <ul> <li>…ends with <code>-cert-v01@openssh.com</code>, then, for the purposes of this list, ignore the <code>-cert-v01@openssh.com</code> suffix.</li> <li>…is <code>dsa</code> or <code>ssh-dss</code>, or is <code>dsa</code> followed by a number, then your key type is <strong>DSA</strong>.</li> <li>…is <code>rsa</code> or <code>ssh-rsa</code>, or is <code>rsa</code> followed by a number, then your key type is <strong>RSA</strong>.</li> <li>…is <code>ecdsa</code> followed by a number, or is <code>ecdsa-sha2-nistp</code> followed by a number, then your key type is <strong>ECDSA</strong>.</li> <li>…is <code>ssh-ed25519</code>, then your key type is <strong>Ed25519</strong>.</li> <li>…is <code>ssh-ed448</code>, then your key type is <strong>Ed448</strong>.</li> </ul> </details> <p>If you do not yet have a (supported) SSH key, we recommend Ed25519 for maximum speed and reasonable availability, otherwise RSA for maximum availability. We do not in general recommend Ed448 because it is not widely implemented (as of January 2026).</p> <details class="example"> <summary>Generating new SSH keys for <code>derivepassphrase</code></summary> <div class="tabbed-set tabbed-alternate" data-tabs="5:3"><input checked="checked" id="__tabbed_5_1" name="__tabbed_5" type="radio" /><input id="__tabbed_5_2" name="__tabbed_5" type="radio" /><input id="__tabbed_5_3" name="__tabbed_5" type="radio" /><div class="tabbed-labels"><label for="__tabbed_5_1">OpenSSH</label><label for="__tabbed_5_2">PuTTY</label><label for="__tabbed_5_3">GnuPG</label></div> <div class="tabbed-content"> <div class="tabbed-block"> <p>The resulting key will be stored in <code>~/.ssh/my-vault-ed25519-key</code>, using “vault key” as a comment. Replace <code>-t ed25519</code> with <code>-t rsa</code> if generating an RSA key, and adapt the filename accordingly.</p> <div class="highlight"><pre><span></span><code><span class="gp">$ </span>ssh-keygen<span class="w"> </span>-t<span class="w"> </span>ed25519<span class="w"> </span>-f<span class="w"> </span>~/.ssh/my-vault-ed25519-key<span class="w"> </span>-C<span class="w"> </span><span class="s2">"vault key"</span> <span class="go">Generating public/private ed25519 key pair.</span> <span class="go">Enter passphrase for ".../.ssh/my-vault-ed25519-key" (empty for no passphrase): </span> <span class="go">Enter same passphrase again:</span> <span class="go">Your identification has been saved in .../.ssh/my-vault-ed25519-key</span> <span class="go">Your public key has been saved in .../.ssh/my-vault-ed25519-key.pub</span> <span class="go">The key fingerprint is:</span> <span class="go">SHA256:0h+WAokssfhzfzVyuMLJlIcWyCtk5WiXI8BHyhXYxC0 vault key</span> <span class="go">The key's randomart image is:</span> <span class="go">+--[ED25519 256]--+</span> <span class="go">|o B=+ |</span> <span class="go">|.=oE = . |</span> <span class="go">|.oX @ + |</span> <span class="go">| = + o * . . |</span> <span class="go">| + o * S B |</span> <span class="go">| + * + O o |</span> <span class="go">| * o . |</span> <span class="go">| o |</span> <span class="go">| |</span> <span class="go">+----[SHA256]-----+</span> </code></pre></div> <p>(The key fingerprint and the randomart image will naturally differ, as they are key-specific.)</p> </div> <div class="tabbed-block"> <p>The resulting key will be stored in <code>~/.ssh/my-vault-ed25519-key.ppk</code>, using “vault key” as a comment. Replace <code>-t ed25519</code> with <code>-t rsa</code> if generating an RSA key, and adapt the filename accordingly.</p> <div class="highlight"><pre><span></span><code><span class="gp">$ </span>puttygen<span class="w"> </span>-t<span class="w"> </span>ed25519<span class="w"> </span>-o<span class="w"> </span>~/.ssh/my-vault-ed25519-key.ppk<span class="w"> </span>-C<span class="w"> </span><span class="s2">"vault key"</span> <span class="go">Enter passphrase to save key: </span> <span class="go">Re-enter passphrase to verify: </span> </code></pre></div> </div> <div class="tabbed-block"> <p>Not supported natively. A different SSH client distribution such as OpenSSH or PuTTY is necessary to create SSH keys specifically.</p> <p>Alternatively, GnuPG supports reusing keys in its native OpenPGP format for SSH as long as the underlying key type is compatible. First, obtain the keygrip for the correct key you may want to use. (<a href="#agent-specific-notes">See the agent-specific notes for GnuPG terminology.</a>)</p> <div class="highlight"><pre><span></span><code><span class="gp">$ </span>gpg<span class="w"> </span>--list-keys<span class="w"> </span>--with-keygrip<span class="w"> </span>sample-key@example.com <span class="go">sec rsa4096 2026-01-21 [SC] [expires: 2026-01-24]</span> <span class="go"> 375509534445A9CA834F15E21A1525F3334C607A</span> <span class="go"> Keygrip = D91EBFAC7C503623B8BCC628B5B5A233AD7CA219</span> <span class="go">uid [ultimate] Sample Key <sample-key@example.com></span> <span class="go">ssb rsa4096 2026-01-21 [E] [expires: 2026-01-24]</span> <span class="go"> Keygrip = E3F1DC21B524B5515C16D8E6112F20F3810C64F2</span> </code></pre></div> <p>(Note that OpenPGP <em>subkeys</em> have a different keygrip than the <em>main key</em>. Be sure to use the correct one, e.g., D91EBFAC7C503623B8BCC628B5B5A233AD7CA219.)</p> <div class="tabbed-set tabbed-alternate" data-tabs="6:2"><input checked="checked" id="__tabbed_6_1" name="__tabbed_6" type="radio" /><input id="__tabbed_6_2" name="__tabbed_6" type="radio" /><div class="tabbed-labels"><label for="__tabbed_6_1">before v2.3.7</label><label for="__tabbed_6_2">v2.3.7 and later</label></div> <div class="tabbed-content"> <div class="tabbed-block"> <p>Add the keygrip (on a line of its own) to <code>sshcontrol</code>.</p> <div class="highlight"><pre><span></span><code><span class="gp">$ </span><span class="nb">echo</span><span class="w"> </span>D91EBFAC7C503623B8BCC628B5B5A233AD7CA219<span class="w"> </span>>><span class="w"> </span>~/.gnupg/sshcontrol </code></pre></div> </div> <div class="tabbed-block"> <p>Set a key attribute to permit this key’s use in SSH:</p> <div class="highlight"><pre><span></span><code><span class="gp">$ </span>gpg-connect-agent<span class="w"> </span><span class="s1">'KEYATTR D91EBFAC7C503623B8BCC628B5B5A233AD7CA219 Use-for-ssh: true'</span><span class="w"> </span>/bye <span class="go">OK</span> </code></pre></div> </div> </div> </div> </div> </div> </div> </details> <hr /> <div class="admonition abstract"> <p class="admonition-title">Further reading</p> <p>→ <a href="../../how-tos/ssh-key/">How to set up <code>derivepassphrase vault</code> with an SSH key</a></p> </div> <div class="footnote"> <hr /> <ol> <li id="fn:gpg-agent-openssh-emulation-experimental"> <p>This experimental status is presumably specifically about the communication system in use (Windows named pipes), which is only available on Windows and thus impossible to test on other operating systems. The GnuPG developers appear to have insufficient access to Windows machines to continue testing and maintaining this subsystem. (<a href="../../wishlist/windows-ssh-agent-support/">The same lack of access to Windows machines originally affected <em>our</em> development of SSH agent support on Windows for <code>derivepassphrase</code> as well.</a>) <a class="footnote-backref" href="#fnref:gpg-agent-openssh-emulation-experimental" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:pageant-socket-address"> <p>In particular, Pageant uses a non-constant, long and pseudo-random socket address that is (<a href="https://en.wikipedia.org/wiki/Capability-based_security">by design</a>) computationally infeasible to compute for other processes not running in the same user’s session. This would be non-sensical to require the user to compute externally, then set <code>SSH_AUTH_SOCK</code> accordingly, instead of teaching <code>derivepassphrase</code> to compute the address itself. <a class="footnote-backref" href="#fnref:pageant-socket-address" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:feature-support"> <p>This indicates support in principle, on this hardware/software/system combination, for interfacing with an SSH agent. At runtime, this could still fail, e.g. because the SSH agent isn’t actually running, because <code>derivepassphrase</code> is trying to connect to the wrong address, etc. <a class="footnote-backref" href="#fnref:feature-support" title="Jump back to footnote 3 in the text">↩</a></p> </li> </ol> </div> </article> </div> </div> </main> <footer class="md-footer"> <nav class="md-footer__inner md-grid" aria-label="Footer" > <a href="../derivepassphrase.vault/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Submodule vault"> <div class="md-footer__button md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class="md-footer__title"> <span class="md-footer__direction"> Previous </span> <div class="md-ellipsis"> Submodule vault </div> </div> </a> <a href="../../explanation/" class="md-footer__link md-footer__link--next" aria-label="Next: Explanation overview"> <div class="md-footer__title"> <span class="md-footer__direction"> Next </span> <div class="md-ellipsis"> Explanation overview </div> </div> <div class="md-footer__button md-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class="md-copyright"> <div class="md-copyright__highlight"> Copyright © 2026 Marco Ricci (the-13th-letter) </div> Made with <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener"> Material for MkDocs </a> and <a href="https://mkdocstrings.github.io/python/" target="_blank" rel="noopener"> mkdocstrings-python </a> </div> </div> </div> </footer> </div> <div class="md-dialog" data-md-component="dialog"> <div class="md-dialog__inner md-typeset"></div> </div> </body> </html>