{"id":19434472,"url":"https://github.com/mlin/stakesign","last_synced_at":"2025-07-26T13:37:19.849Z","repository":{"id":55478227,"uuid":"324310295","full_name":"mlin/stakesign","owner":"mlin","description":"Sign files via blockchain + put your money where your mouth is","archived":false,"fork":false,"pushed_at":"2020-12-28T12:45:21.000Z","size":142,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-19T09:22:57.522Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mlin.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}},"created_at":"2020-12-25T07:17:58.000Z","updated_at":"2022-02-16T18:28:51.000Z","dependencies_parsed_at":"2022-08-15T01:11:01.667Z","dependency_job_id":null,"html_url":"https://github.com/mlin/stakesign","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlin%2Fstakesign","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlin%2Fstakesign/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlin%2Fstakesign/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlin%2Fstakesign/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mlin","download_url":"https://codeload.github.com/mlin/stakesign/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240614681,"owners_count":19829390,"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-11-10T14:46:32.770Z","updated_at":"2025-02-25T06:24:38.982Z","avatar_url":"https://github.com/mlin.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stakesign\n\n### Sign files via blockchain + put your money where your mouth is\n\nThis project helps open-source developers, and other DIY-types, who'd like to affix user-verifiable **digital signatures on files, code, and container images**. It provides a way to **sign with a cryptocurrency wallet**, instead of a separate GnuPG keypair or X.509 certificate.\n\nIt furthermore defines that **signatures remain valid only while the signing address holds a *stake* of unspent cryptocurrency**. The stake bonds the publisher to keep their signing key safe \u0026 secure, even if they lose interest in the signed products; or otherwise, allows for its revocation with immediate, global effect. These properties aren't as easily achieved by other P2P signing mechanisms.\n\n**Signatures are broadcast in public blockchain transactions,** providing an irrefutably timestamped audit trail, and a succinct delivery mechanism (transaction ID). Alternatively, one can communicate a signature off-chain and refer to the public ledger just to confirm the stake (foregoing the intrinsic audit trail).\n\nAnother salient property is that **this doesn't require dedicated software;** one can generate and verify signatures using standard blockchain tools and Unix programs. But, we've also prepared a Python command-line tool that smooths out the process.\n\n### Quick start example\n\nEthereum transaction [0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf](https://etherscan.io/tx/0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf) is my signature for the MIT [LICENSE](https://github.com/mlin/stakesign/raw/main/LICENSE) file in this repo. Open the transaction link, expand **Click to see More**, then **View Input As \u003e UTF-8** to find:\n\n[![MEW Send Transaction screenshot](doc/EtherscanData.png)](https://etherscan.io/tx/0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf)\n\nThis is nothing more than [GNU sha256sum](https://www.gnu.org/software/coreutils/manual/html_node/sha2-utilities.html)'s output appended to a one-line JSON header. The header advises the recipient to reject the signature if the [ETH balance of the signing key](https://etherscan.io/address/0x83cee747e4bcff80938ea1056f925d1c24412f0b) is below 0.42. To verify this signature at the command line,\n\n```\n$ pip3 install stakesign\n# on macOS, also: brew install coreutils\n# coming soon: conda install -c conda-forge stakesign\n\n# then download LICENSE and verify it:\n$ wget https://github.com/mlin/stakesign/raw/main/LICENSE\n$ stakesign verify 0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf\nTrusting ETH gateway:\thttps://cloudflare-eth.com\n         Transaction:\t0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf\n    Signer's address:\t0x83Cee747E4BCFF80938eA1056F925d1c24412f0b\n Signature timestamp:\t2020-12-25 08:14:44Z\nSigner's balance now:\t1.096695296\t≥ 0.42 ETH from stakeAd\t🗹\n  Trusting local exe:\t/usr/bin/sha256sum\n\nLICENSE: OK\n\n🗹\tSuccess\n```\n\n`stakesign verify` looks up the signature through a public Ethereum gateway, displays the signing address and its current ETH balance, then runs `sha256sum` to verify the local file's contents against the signed digests. You just need to know that [0x83Cee747E4BCFF80938eA1056F925d1c24412f0b](https://etherscan.io/address/0x83cee747e4bcff80938ea1056f925d1c24412f0b) is in fact *my* key, e.g. as reported here and on [my homepage](https://www.mlin.net/). Try tampering with the local copy of LICENSE to see the tool reject it.\n\n### Verifying manually\n\nThe tool doesn't really do anything interesting, and you don't have to trust it. To verify the signature manually, run `sha256sum` on your copy of LICENSE, [look up the public transaction data](https://etherscan.io/tx/0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf) (**Click to see More**, **View As \u003e UTF-8**) and check that:\n\n1. your SHA256 file digest(s) match the published signature\n2. the signature transaction's From address is what the publisher has announced\n3. that address *currently* [holds an ETH balance](https://etherscan.io/address/0x83cee747e4bcff80938ea1056f925d1c24412f0b) evincing the signer's ongoing interest in securing it (perhaps, but not necessarily, the amount advertised inside the signature)\n\nAdditional subjective factors you could look into: (4) the signature transaction's timestamp seems within your expectations; (5) the public activity ledger for the signing address doesn't seem suspicious, e.g. signing tons of stuff the publisher isn't associated with.\n\nIf you're paranoid about our Etherscan links, then you can easily cross-reference similar sites for browsing the public blockchain (e.g. [1](https://ethplorer.io/tx/0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf) [2](https://blockchair.com/ethereum/transaction/0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf) [3](https://eth.btc.com/txinfo/0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf) [4](https://www.blockchain.com/eth/tx/0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf)); or even your local node.\n\n### Signing files\n\nFirst, you load an Ethereum address with ETH greater than the intended stake amount (to afford transaction fees), and announce your address through various media.\n\nThen, `stakesign prepare` runs `sha256sum` on local files and formulates the payload data, which you then use your cryptocurrency wallet to sign and broadcast.\n\n```\n$ stakesign prepare --stake 0.42 LICENSE\nTrusting local exe:\t/usr/bin/sha256sum\n\n{\"stakesign\":\"sha256sum\",\"stakeAd\":{\"ETH\":0.42}}\n2f91a6f33f4f2d72ed4cd6c363f1e72cddd726b4d35c2af35356f256a54e75a0  LICENSE\n\n-- Transaction input data for signing (one long line):\n\n0x7b227374616b657369676e223a2273686132353673756d222c227374616b654164223a7b22455448223a302e34327d7d0a3266393161366633336634663264373265643463643663333633663165373263646464373236623464333563326166333533353666323536613534653735613020204c4943454e53450a\n\n```\n\nSee [doc/Signing-MEW.md](doc/Signing-MEW.md) for a walkthrough using [MyEtherWallet](https://www.myetherwallet.com/) to complete the process. Other wallets that let you paste the transaction input hex string (aka \"contract data\") should work too. We'll make this process smoother in the future; offloading it for now allowed our prototype code to avoid handling any real cryptography.\n\nOnce your signature is published on the blockchain, attach the signature transaction ID to your products and point your users to here for `stakesign verify` or the manual procedure. (Hey, we've got to start somewhere...)\n\n### Signing git revisions \u0026 Docker images\n\nBeyond files, `stakesign` has helper modes for signing git commits \u0026 tags and Docker images. Verification examples:\n\n```\n$ git clone --branch v1.1.0 https://github.com/mlin/spVCF.git \u0026\u0026 cd spVCF\n$ stakesign verify 0x248d9fac23ab037111c4bffdf25dd09f9dbdf1c34c6114365f0bdbe50294c483\n$ docker pull quay.io/mlin/glnexus:v1.2.5 \u0026\u0026 docker pull quay.io/mlin/glnexus:v1.2.6\n$ stakesign verify 0xd071c0e8fbcbcab8b92f9098c5250d7e1c003f222c94fe0729669bae02ae3acf\n```\n\n* *See [doc/git_docker.md](doc/git_docker.md) for full detais*\n\n### Off-chain signatures\n\n*To be written*\n\n### Discussion\n\nThe stake amount is a social convention: users should expect a high-profile publisher to post something substantial (taking `stakeAd` as advisory only). Besides bonding the publisher, the stake poses one more hurdle to tricking users into accepting a signature by the wrong key.\n\nShould the publisher's key become compromised, its signatures will probably be \"revoked\" immediately, when the ETH stake is stolen. Otherwise, the publisher can revoke by transferring the stake anywhere else. In extremis, they might have to deploy a bot to continually sweep all the ETH pumped in by attackers trying to keep their forged signatures valid! (Talk about softening the blow.)\n\nWe built our prototype atop Ethereum only because its wallets, browsers, and libraries handle [similar small data payloads](https://medium.com/mycrypto/why-do-we-need-transaction-data-39c922930e92) routinely. There's no dapp or smart contract involved, which we consider a feature. Bitcoin would work almost as well, just with [some cumbersome details](https://ledgerjournal.org/ojs/ledger/article/download/101/93/) around the signing and verification process.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmlin%2Fstakesign","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmlin%2Fstakesign","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmlin%2Fstakesign/lists"}