{"id":30780422,"url":"https://github.com/soatok/freeon","last_synced_at":"2025-10-05T10:32:00.235Z","repository":{"id":309153497,"uuid":"1032032567","full_name":"soatok/freeon","owner":"soatok","description":"FOSS Resists Extralegal Executive Overreaching Nations - Threshold digital signature library in Go","archived":false,"fork":false,"pushed_at":"2025-09-02T05:20:11.000Z","size":134,"stargazers_count":78,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-02T07:07:47.423Z","etag":null,"topics":["code-signing","command-line-tool","distributed-key-generation","ed25519","frost","rfc-9591","supply-chain-security","threshold-signatures"],"latest_commit_sha":null,"homepage":"https://soatok.blog/2025/08/09/improving-geographical-resilience-for-distributed-open-source-teams-with-freon/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soatok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-04T17:43:08.000Z","updated_at":"2025-09-02T05:20:14.000Z","dependencies_parsed_at":"2025-08-10T08:23:22.130Z","dependency_job_id":"0e4312c7-ecf6-4445-8e5b-cf2bbce7b56a","html_url":"https://github.com/soatok/freeon","commit_stats":null,"previous_names":["soatok/freon","soatok/freeon"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/soatok/freeon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soatok%2Ffreeon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soatok%2Ffreeon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soatok%2Ffreeon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soatok%2Ffreeon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soatok","download_url":"https://codeload.github.com/soatok/freeon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soatok%2Ffreeon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273728157,"owners_count":25157136,"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","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["code-signing","command-line-tool","distributed-key-generation","ed25519","frost","rfc-9591","supply-chain-security","threshold-signatures"],"created_at":"2025-09-05T07:45:13.272Z","updated_at":"2025-10-05T10:32:00.134Z","avatar_url":"https://github.com/soatok.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FREEON\n\n\u003e FOSS Resists Extralegal Executive Overreaching Nations\n\n[![Build Status](https://github.com/soatok/freeon/actions/workflows/ci.yml/badge.svg)](https://github.com/soatok/freeon/actions/workflows/ci.yml)\n\nFREEON implements FROST ([RFC 9591](https://www.rfc-editor.org/rfc/rfc9591.html)) to allow geographically distributed teams produce digital signatures.\n\nEach share of the signing key is encrypted locally using [age](https://github.com/FiloSottile/age).\n\n\u003e [!WARNING]\n\u003e This software is a minimum viable product (MVP) and is only in the **alpha** stage of development. It has not been audited. Do not use this in production yet!\n\n\u003e This project is not affiliated with [the Chemours Company](https://en.wikipedia.org/wiki/Freon).\n\n## Installation\n\n### Freeon Clients\n\n```terminal\ngo install github.com/soatok/freeon/client@latest\n```\n\n#### For Developers\n\nYou can also clone the repository to install the client locally:\n\n```terminal\ngit clone https://github.com/soatok/freeon.git\ncd freeon/client\ngo install\n```\n\n### Freeon Coordinators\n\n\u003e [!WARNING]\n\u003e The coordinator is expected to run on a private network, such as [Tailscale](https://tailscale.com),\n\u003e [ZeroTier](https://www.zerotier.com), or within a Virtual Private Cloud (VPC) from AWS, Azure, or GCP.\n\u003e\n\u003e In the future, we will develop a standalone coordinator that can safely be deployed on the public-facing\n\u003e Internet, but this was cut from the alpha release due to time constraints.\n\n```terminal\ngit clone https://github.com/soatok/freeon.git\ncd freeon\ngo build -o coordinator ./coordinator\n./coordinator\n```\n\n## Usage\n\nThe order of operations is as followed:\n\n1. Perform the **Distributed Key Generation** ceremony once, for each Ed25519 keypair.\n   1. One client tell the coordinator to initiate a new DKG. The number of parties and threshold are required at this step.\n   2. The coordinator sets up a session that other clients can connect to, and gives the DKG Group ID to the client. This is to be shared with other users. The Group ID is not sensitive; it only serves to allow multiple keys be managed by one Freeon coordinator.\n   3. Once every participating user enrolls in the DKG ceremony, the final public key is calculated and shared with each participant.\n   4. Each client encrypts their Shamir Share, along with their Party ID and the group identifier, locally.\n2. For each message to be signed:\n   1. One client proposes a message to be signed to the coordinator.\n   2. Each participating client connects and commits to the message (FROST Round 1).\n   3. Each participating client connects and publishes their share of the final signature (FROST Round 2).\n   4. The coordinator aggregates the signature and releases it to each connected client.\n\nWe will document each command in tandem with this order of operations.\n\n### Distributed Key Generation\n\nTo initiate a new DKG group, one of the clients with access to the coordinator will run the following command (replace 7 and 3 with\nthe number of participants and threshold needed to perform a signature operation, respectively):\n\n```terminal\nfreeon keygen create -h hostname:port -n 7 -t 3\n```\n\nUpon success, a Group ID will be returned. This is to be shared with the other participants, who will pass it as an extra argument:\n\n```terminal\nfreeon keygen join -h hostname:port -g [group-id-goes-here]\n```\n\nThis will maintain a connection with the coordinator until all `n` participants have connected. Afterwards, a copy of the public key will be returned to each client.\n\n#### Optional Arguments\n\nIf you provide a public key (`-r [RECIPIENT]`) as an optional argument, the Freeon client will use [age](https://age-encryption.org) to encrypt the share locally. This public key can be an age public key or an OpenSSH public key.\n\n### Signature Generation\n\n#### Initiate Signature Ceremony\n\nTo initiate a key ceremony, the following information is needed:\n\n1. The Group ID used during Key Generation.\n2. The message intended to be signed.\n\nThe message can be passed as a file name or via `STDIN`, like so:\n\n```terminal\nfreeon sign create -g [group-id-goes-here] file-with-message.txt\necho -n \"MESSAGE TO BE SIGNED\" | freeon sign create -g [group-id-goes-here]\n```\n\nThis will initialize a signature in progress and return a Ceremony ID.\n\n\u003e [!NOTE]\n\u003e You do not need a key share to initiate a signature proposal. This is an intentional design feature to allow\n\u003e CI/CD pipelines queue up a Signature Ceremony that clients can then opt into participating in.\n\n##### Optional Arguments\n\nBy default, the final signature will be returned as a 128-character hex-encoded string (encoded as `R || z`).\nYou can pass an optional `--openssh` flag to return an OpenSSH-compatible signature.\n\n```terminal\nfreeon sign create --openssh -g [group-id-goes-here] file-with-message.txt\necho -n \"MESSAGE TO BE SIGNED\" | freeon sign create --openssh -g [group-id-goes-here]\n```\n\n##### Terminating Incomplete Ceremonies\n\nYou can run this command to flush any incomplete ceremonies.\n\n```terminal\nfreeon terminate [ceremony-id-goes-here]\n```\n\n\u003e [!WARNING]\n\u003e You do not need privileged access to perform this step.\n\n#### Participate In Signature Ceremony\n\nEach client will need to run this command to participate in the ceremony.\n\n```terminal\nfreeon sign join -c [ceremony-id] file-with-message.txt\necho -n \"MESSAGE TO BE SIGNED\" | freeon sign join -c [ceremony-id]\n\n# Identical:\nfreeon sign join --ceremony [ceremony-id] file-with-message.txt\necho -n \"MESSAGE TO BE SIGNED\" | freeon sign join --ceremony [ceremony-id]\n```\n\n##### Optional Arguments\n\nYou can furthermore pass the `-i` or `--identity` flag to specify the file path for your age secret keys.\n\n```terminal\nfreeon sign join -c [ceremony-id] -i /path/to/age.keys file-with-message.txt\necho -n \"MESSAGE TO BE SIGNED\" | freeon sign join -i /path/to/age.keys -c [ceremony-id]\n\n# Identical\nfreeon sign join --ceremony [ceremony-id] --identity /path/to/age.keys file-with-message.txt\necho -n \"MESSAGE TO BE SIGNED\" | freeon sign join --identity /path/to/age.keys --ceremony [ceremony-id]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoatok%2Ffreeon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoatok%2Ffreeon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoatok%2Ffreeon/lists"}