{"id":17330312,"url":"https://github.com/foxboron/clave","last_synced_at":"2025-04-14T17:53:58.516Z","repository":{"id":144212275,"uuid":"93276392","full_name":"Foxboron/clave","owner":"Foxboron","description":"🔒 Remote signing","archived":false,"fork":false,"pushed_at":"2017-11-08T14:57:53.000Z","size":3025,"stargazers_count":26,"open_issues_count":3,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T06:23:45.683Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Foxboron.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2017-06-03T22:07:37.000Z","updated_at":"2024-10-24T08:05:42.000Z","dependencies_parsed_at":"2023-05-19T06:30:29.864Z","dependency_job_id":null,"html_url":"https://github.com/Foxboron/clave","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Foxboron%2Fclave","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Foxboron%2Fclave/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Foxboron%2Fclave/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Foxboron%2Fclave/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Foxboron","download_url":"https://codeload.github.com/Foxboron/clave/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248931822,"owners_count":21185246,"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":[],"created_at":"2024-10-15T14:50:55.068Z","updated_at":"2025-04-14T17:53:58.494Z","avatar_url":"https://github.com/Foxboron.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"clave\n=====\nClave enables remote GPG signing without exposing your private key to a remote\nserver. It generates the signing hash on the remote server, and lets you sign\nthe hash locally with your private key.\n\nThe tool is currently under development, and any suggestions or improvements are\nappreciated!\n\n## Why\nThe signature hash used for OpenPGP signatures requires a few things:\n- signature type\n- public-key algorithm\n- hashed subpackets \n\nThe above fields are concatenated with the data being signed to create the\nsigning hash. This prevents you from running `sha256sum` over your file to\ncreate an OpenPGP signature.\n\nThe OpenPGP RFC explains this: https://tools.ietf.org/html/rfc4880#section-5.2.3\n\nThe problem occurs when you have created a 3 GB artefact on your build server,\nand need to sign this. You could download the file, but this is slow and\ncumbersome. There are options to forward the signing socket to the remote\nserver which could pose as a solution.\n\nhttps://lists.archlinux.org/pipermail/arch-general/2017-January/042987.html\n\nThere has also been previous discussion on the pacman-dev mailing list when\nsigning was brought up. This in turn led to a discussion on the GnuPG mailing\nlist where Koch made it clear this won't be implemented.\n \nhttps://lists.archlinux.org/pipermail/pacman-dev/2011-June/013333.html  \nhttps://lists.gnupg.org/pipermail/gnupg-users/2011-June/042076.html  \n\n\n## How\nGolang implements the entire OpenPGP system with high level abstractions. It's\npretty neat and easy to use. To create the signature we initiate the signing\nwith the public key, along with a default configuration for the signature packet.\n\nSince the public key is used, the actual signing parts of the library will\ncrash. We dispatch the actual signing into its own thread, and recover from the\ncrash. We can then grab the hash from the Hash struct we made, and use this in\nour signature request.\n\nhttps://github.com/Foxboron/clave/blob/master/src/signature.go#L47\n\nThe signature request created by clave contains the filename, Unix timestamp and\nthe signing hash. This is used locally to resume the signing process by faking a\nhash struct. This enables us to make sure the OpenPGP library never modifies the\nhash, and that our signing hash will always be returned. This creates the valid\nsignature locally.\n\n\n## Drawbacks\nThere are some drawbacks, the Go openpgp library is weird, so reading from\nkeyrings is not trivial. The current implementation exports your key from\nGnuPG, and then decrypts the key, where you end up typing the password twice.\n\nThe other problem is if you inherently trust your remote server. Clave is more\nan experiment if this is a useful compromise in some cases (like a build server,\nwhere reproducible packages can be built, and the signed hash verified).\n\n\n## Usage\n```\n$ cat ~/.clave.yml \nkeyid: 9C02FF419FECBE16\n$ clave gen ./tests/test \u003e ./requests\n$ cat ./requests \n[{\"Name\":\"./tests/test\",\"UnixTime\":1507146122,\"Digest\":\"8201143f42b240e803f9b36b70b610f7031eb05c6b2b6f7195bfe9c7b5e62997\"}]%                                                                                                          \n$ cat ./requests | clave sign\n$ cd ./tests \u0026\u0026 gpg --verify test.sig \ngpg: assuming signed data in 'test'\ngpg: Signature made Wed 04 Oct 2017 09:42:02 PM CEST\ngpg:                using RSA key 9C02FF419FECBE16\ngpg: Good signature from \"Morten Linderud \u003cmorten@linderud.pw\u003e\" [ultimate]\ngpg:                 aka \"Morten Linderud \u003cmcfoxax@gmail.com\u003e\" [ultimate]\ngpg:                 aka \"Morten Linderud \u003cmorten.linderud@fribyte.uib.no\u003e\" [ultimate]\ngpg:                 aka \"Morten Linderud \u003cmorten.linderud@student.uib.no\u003e\" [ultimate]\ngpg:                 aka \"Morten Linderud \u003cfoxboron@archlinux.org\u003e\" [ultimate]\n$ cat request | clave verify -\n2017/10/10 22:22:33 Correct signature request!\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoxboron%2Fclave","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoxboron%2Fclave","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoxboron%2Fclave/lists"}