{"id":20384962,"url":"https://github.com/d-e-s-o/ssh-gpg-agent","last_synced_at":"2025-04-12T09:33:14.554Z","repository":{"id":57668442,"uuid":"170078004","full_name":"d-e-s-o/ssh-gpg-agent","owner":"d-e-s-o","description":"An SSH agent implementation that transparently supports PGP encrypted private SSH keys.","archived":false,"fork":false,"pushed_at":"2024-04-22T00:59:59.000Z","size":119,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-07T14:16:37.789Z","etag":null,"topics":["authentication","ed25519","gnupg","gpg","openssh","pgp","rsa","ssh","ssh-agent"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d-e-s-o.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-11T06:17:54.000Z","updated_at":"2024-12-23T00:33:12.000Z","dependencies_parsed_at":"2024-04-22T01:53:44.567Z","dependency_job_id":"393c0f1e-136b-4756-a065-a16ecd7a0a9e","html_url":"https://github.com/d-e-s-o/ssh-gpg-agent","commit_stats":{"total_commits":48,"total_committers":1,"mean_commits":48.0,"dds":0.0,"last_synced_commit":"dc401a1d126fd7ac45f815fd7d4bb9c3ef50db0e"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-e-s-o%2Fssh-gpg-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-e-s-o%2Fssh-gpg-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-e-s-o%2Fssh-gpg-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-e-s-o%2Fssh-gpg-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d-e-s-o","download_url":"https://codeload.github.com/d-e-s-o/ssh-gpg-agent/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248545915,"owners_count":21122240,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","ed25519","gnupg","gpg","openssh","pgp","rsa","ssh","ssh-agent"],"created_at":"2024-11-15T02:31:03.552Z","updated_at":"2025-04-12T09:33:14.530Z","avatar_url":"https://github.com/d-e-s-o.png","language":"Rust","readme":"[![pipeline](https://github.com/d-e-s-o/ssh-gpg-agent/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/d-e-s-o/ssh-gpg-agent/actions/workflows/test.yml)\n[![crates.io](https://img.shields.io/crates/v/ssh-gpg-agent.svg)](https://crates.io/crates/ssh-gpg-agent)\n[![rustc](https://img.shields.io/badge/rustc-1.71+-blue.svg)](https://blog.rust-lang.org/2023/07/13/Rust-1.71.0.html)\n[![license](https://img.shields.io/github/license/d-e-s-o/ssh-gpg-agent.svg)](https://github.com/d-e-s-o/ssh-gpg-agent/blob/master/LICENSE)\n\nssh-gpg-agent\n=============\n\n- [Changelog](CHANGELOG.md)\n\n**ssh-gpg-agent** is an alternative SSH agent implementation that\ntransparently supports PGP encrypted private SSH keys, instead of\nrelying on password protection. Unlike SSH agents as provided by GnuPG\nor OpenSSH, there is no need to \"add\" them to the agent -- key discovery\nis automatic in a given directory.\n\n\n### The Context\n\nFor a given user, there can be merit in having a single SSH key per host\ninstead of a shared one for all hosts a given user wants to connect to.\nBenefits include but are not necessary limited to:\n- Compromise of a key only compromises a single service\n- Simplified tracing of where a given key was used: the file name can\n  identify the service it is used for while the public key's comment (as\n  visible in the service's `authorized_keys` file) acts as a back link\n  to the holder of the private key\n- Potential for plausible deniability not present when a single key is\n  used for all services -- same key means same user\n\nAt the same time it is advisable to not store private keys in\nunencrypted form on any system. Password protection comes to the rescue.\n\nWhile a password provides security and ease of mind, it is often times\ninconvenient: repeated entry of passwords is necessary each and every\ntime an SSH connection is established.\n\nThis is where SSH agents help out, which, upon asking for the key's\npassword once, will cache the sensitive key material for a specific time\nor until the system is rebooted, depending on user preference.\n\n\n### The Problem\n\nHowever, with a lot of systems to connect to, each using a separate key\npair for authentication purposes, entering a password for each one of\nthose -- even if that happens just once over the uptime of a system --\nis still a significant burden on the user.\n\n\n### A Solution\n\nIn order to circumvent the repeated entry of passwords for encrypted\nkeys, why not piggy back on a program available for encryption purposes\non many systems anyway: GnuPG.\n\n**ssh-gpg-agent** acts as an SSH agent that assumes PGP encrypted\nprivate SSH key files and can decrypt those transparently through GnuPG.\nAssuming an agent is used for GnuPG keys, decryption of SSH keys can be\ndemoted to a background activity not requiring any user interaction\nwhatsoever.\n\nAdditionally, if a smart card is used for decryption, there is the added\nbenefit that simply removing it from the system will also prevent the\nautomated usage of SSH keys.\n\n\nSetup\n-----\n\nAs a first step to using the agent, existing password protected SSH keys\nshould be re-encrypted with GnuPG.\n\nThe following function can be used to simplify the task:\n```sh\nfunction encrypt() {\n  if [ $# -le 1 ]; then\n    echo \"Usage: encrypt \u003cssh-key-file\u003e \u003cgpg-identity-to-encrypt-to\u003e\"\n    return\n  fi\n\n  mkfifo -m 0600 _fifo \u0026\u0026 \\\n  (cat \"${1}\" \u003e _fifo \u0026\u0026 \\\n   cat \"${1}\" \u003e _fifo \u0026\u0026 \\\n   gpg --encrypt --recipient=\"${2}\" --yes --output=\"${1}\".gpg \u003c _fifo \u0026) \u0026\u0026 \\\n  ssh-keygen -p -N \"\" -f _fifo \u0026\u0026 \\\n  rm _fifo\n}\n```\n\nThis function, applied to a single key, will ask for the key's current\npassword, decrypt it, and encrypt it to the given GnuPG identity or\nrecipient.\n\nFor example:\n```\nencrypt '~/.ssh/d-e-s-o@github:access_2018-01-01' 'deso@posteo.net'\n```\n\nThe result is a new file with the extension `.gpg` that contains the\nencrypted key. The original file is left untouched. It can be kept\naround as a fall back (e.g., in the case of smart card usage where the\ncard is not available).\n\nAfter installation of the agent (through `cargo install ssh-gpg-agent`,\nfor example) it can be started directly. By default it will work on the\nuser's `~/.ssh/` directory and it will be used to serve identities that\nhave an associated `.gpg` file available.\n\nThe agent listens for requests in a Unix domain socket, located in the\nsystem's tmp directory with the name `ssh-gpg-agent.sock`.\n\nThe `SSH_AUTH_SOCK` environment variable should be pointed to this path\nto instruct `ssh` to use **ssh-gpg-agent** if system-wide usage is\ndesired.\n\nAlternatively, if the agent is to be used only for a subset of hosts,\nusage of the agent can be configured to the hosts in question in\n`~/.ssh/config`:\n```\nHost github\n  Hostname github.com\n  User git\n  IdentityFile ~/.ssh/d-e-s-o@github:access_2018-01-01\n  # Use ssh-gpg-agent for this host:\n  IdentityAgent /tmp/ssh-gpg-agent.sock\n```\n\nAfter this setup, PGP encrypted SSH keys can be transparently decrypted\nand used for authentication with a given host.\n\n\nMore Advantages\n---------------\n\nUsage of **ssh-gpg-agent** provides a couple more advantages over\ntypical work flows:\n- It is no longer necessary to `ssh-add` keys to an agent, which is just\n  an opaque second-tier key management mechanism that often is a source\n  of confusion and/or its involvement simply forgotten\n- The agent is stateless: public keys are loaded on demand; private keys\n  are never cached and instead decrypted for every authentication\n  request (note that a `gpg-agent` being used will still be stateful,\n  but this agent does not introduce additional state to manage)\n- When used in conjunction with a smart card that stores the GnuPG\n  identity's key, physically removing the card is enough to prevent\n  further usage SSH keys managed through the agent\n- It effectively provides a way for multi-factor authentication for the\n  usage of SSH keys when used in conjunction with a smart card (physical\n  card \u0026 PIN in addition to the key itself), which is considered more\n  secure than a mere password\n- Existing password protected key material can stay as-is and be used as\n  a fall back/backup\n\n\nAlternative Approaches\n----------------------\n\n**ssh-gpg-agent** is only one solution to the stated problem of repeated\npassword entry when using per-host SSH keys. Alternative ones include:\n- Pre-setting of passphrases using the `PRESET_PASSPHRASE` `gpg-agent`\n  command (which just adds yet another indirection to the system)\n- GnuPG conceptually supports a `protected-shared-secret` key format\n  which may or may not be usable to have a shared password among keys\n  and perhaps there would be a way to hook this up for SSH keys, but the\n  format is not implemented in current versions of GnuPG (i.e., up to\n  and including version 2.2)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-e-s-o%2Fssh-gpg-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd-e-s-o%2Fssh-gpg-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-e-s-o%2Fssh-gpg-agent/lists"}