{"id":15890359,"url":"https://github.com/dsys/solidity-sigutils","last_synced_at":"2025-08-24T00:14:39.590Z","repository":{"id":57365940,"uuid":"135004898","full_name":"dsys/solidity-sigutils","owner":"dsys","description":"✍️ A Solidity library for verifying Ethereum message multi-signatures.","archived":false,"fork":false,"pushed_at":"2018-07-10T02:50:48.000Z","size":407,"stargazers_count":58,"open_issues_count":1,"forks_count":7,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-10-13T07:49:33.580Z","etag":null,"topics":["ethereum","multisig","signatures","solidity"],"latest_commit_sha":null,"homepage":"","language":"Solidity","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/dsys.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":"2018-05-27T00:49:54.000Z","updated_at":"2024-07-04T16:28:09.000Z","dependencies_parsed_at":"2022-08-23T20:10:31.922Z","dependency_job_id":null,"html_url":"https://github.com/dsys/solidity-sigutils","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/dsys%2Fsolidity-sigutils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsys%2Fsolidity-sigutils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsys%2Fsolidity-sigutils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsys%2Fsolidity-sigutils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dsys","download_url":"https://codeload.github.com/dsys/solidity-sigutils/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221753025,"owners_count":16875073,"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":["ethereum","multisig","signatures","solidity"],"created_at":"2024-10-06T07:05:24.210Z","updated_at":"2024-10-28T00:41:06.065Z","avatar_url":"https://github.com/dsys.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# solidity-sigutils\n\n![Travis](https://img.shields.io/travis/dsys/solidity-sigutils.svg) \n![npm](https://img.shields.io/npm/v/solidity-sigutils.svg)\n\nA solidity library for verifying Ethereum message multi-signatures.\n\nThese utilities make it simple to interact with Ethereum signed messages based on [EIP 191](https://github.com/ethereum/EIPs/issues/191) and [ERC 1077](https://github.com/ethereum/EIPs/pull/1077). They are a building block for Cleargraph's open and decentralized identity system, and can be used for many other purposes in decentralized applications.\n\nYou can sign a transaction/message using your private key by calling [web3.personal.sign()](https://web3js.readthedocs.io/en/1.0/web3-eth-personal.html) using MetaMask, Toshi, or another compatible web3 runtime. All signatures are 65 bytes long with the format `{bytes32 r}{bytes32 s}{uint8 v}`. Multiple signatures are stored densely (no padding) by concatenating them.\n\n[API Reference](#api-reference) \u0026middot; [Read the announcement.](https://medium.com/dsys/now-open-source-friendly-multi-signatures-for-ethereum-d75ca5a0dc5c) \u0026middot; [See tests for examples.](https://github.com/dsys/solidity-sigutils/blob/master/test/TestSignatureUtils.sol)\n\n## Usage\n\n[![solidity-sigutils flow](https://raw.githubusercontent.com/dsys/solidity-sigutils/master/resources/diagram.png)](#working-with-ethereum-signed-messages)\n\n[Signed messages](https://medium.com/@angellopozo/ethereum-signing-and-validating-13a2d7cb0ee3) are an increasingly important tool used by decentralized applications. They enable complex access management and delegation patterns and have greater flexibility than raw transactions. Wallet applications such as MetaMask and Toshi support signing transactions via their web3 provider which contracts can verify using `ecrecover()`.\n\nIn the context of identity management, signed messages play a crucial role in building more secure and accessible wallets. Conventionally, anyone with a user's private key has full control over their wallet. This is a security vulnerability: *any malicious actor with access to the user's private key can steal all funds.*\n\nTo improve security, it makes sense to require multi-factor approval from more than one device for some or all transactions. A so-called \"multisig identity\" often involves a proxy contract that accepts signed transactions from a whitelist of keys. To perform a multisig transaction:\n\n1. **Sign:** The user signs a transaction message with their private key from multiple devices.\n2. **Concatenate:** The user concatenates the message signatures into a single multi-signature.\n3. **Verify:** The user sends the transaction message and concatenated signatures to their proxy verifier contract, which verifies that enough valid signatures have been provided using *solidity-sigutils*.\n4. **Execute:** The proxy contract forwards the transaction to the designated contract.\n\nSigned messages inherit the security of Ethereum's `web3.personal.sign()` and `ecrecover()`. One important benefit over raw transactions is that users can work with trust-less intermediaries without sharing their private keys. For example, signed messages enable complex transaction funding strategies like gas relays which pay for transaction costs on a user's behalf. Additionally, identity contracts may choose to use signed messages to implement advanced functionalities such as account recovery logic that does not rely on centralized authorities.\n\n## Installation\n\nInstall using npm:\n\n    $ npm install --save solidity-sigutils\n\nThen, in your solidity file, use the library:\n\n```solidity\nimport \"solidity-sigutils/contracts/SignatureUtils.sol\";\n\ncontract MyContract {\n\n    using SignatureUtils for *; // optional\n\n    function myFunction(\n        string _personalMessage,\n        bytes _signatures\n    ) public returns (address[]) {\n        // Generate the message hash according to EIP 191\n        bytes32 hash = SignatureUtils.toEthPersonalSignedMessageHash(_personalMessage);\n\n        // Returns the array of addresses which signed hash using their private key\n        return SignatureUtils.recoverAddresses(hash, _signatures);\n        // or use SignatureUtils.recoverAddress(hash, _signatures, 0) for only one signature\n    }\n\n}\n```\n\n## Development\n\nPRs welcome. To install dependencies and start the local development server:\n\n    $ npm install\n    $ npm run migrate\n    $ npm start\n\n### Testing\n\n    $ npm test\n    $ npm run watch # requires watchman: brew install watchman\n\n### Regenerate documentation\n\n    $ npm run gen-docs\n\n### Static analysis with Mythril\n\n    $ make install-mythril\n    $ make myth\n\n## Coda\n\nLicensed under Apache 2.0. Started at [ETHBuenosAires](https://ethbuenosaires.com/).\n\n# API Reference\n* [SignatureUtils](#signatureutils)\n  * [recoverAddress](#function-recoveraddress)\n  * [countSignatures](#function-countsignatures)\n  * [parseSignature](#function-parsesignature)\n  * [toEthPersonalSignedMessageHash](#function-toethpersonalsignedmessagehash)\n  * [toEthBytes32SignedMessageHash](#function-toethbytes32signedmessagehash)\n  * [uintToString](#function-uinttostring)\n  * [recoverAddresses](#function-recoveraddresses)\n\n# SignatureUtils\n\nAlexander Kern \u003calex@cleargraph.com\u003e\n\n## *function* recoverAddress\n\nSignatureUtils.recoverAddress(_hash, _signatures, _pos) `pure` `1c2a15b8`\n\n**Recovers an address using a message hash and a signature in a bytes array.**\n\n\nInputs\n\n| **type** | **name** | **description** |\n|-|-|-|\n| *bytes32* | _hash | The signed message hash |\n| *bytes* | _signatures | The signatures bytes array |\n| *uint256* | _pos | The signature's position in the bytes array (0 indexed) |\n\n\n## *function* countSignatures\n\nSignatureUtils.countSignatures(_signatures) `pure` `33ae3ad0`\n\n**Counts the number of signatures in a signatures bytes array. Returns 0 if the length is invalid.**\n\n\u003e Signatures are 65 bytes long and are densely packed.\n\nInputs\n\n| **type** | **name** | **description** |\n|-|-|-|\n| *bytes* | _signatures | The signatures bytes array |\n\n\n## *function* parseSignature\n\nSignatureUtils.parseSignature(_signatures, _pos) `pure` `b31d63cc`\n\n**Extracts the r, s, and v parameters to `ecrecover(...)` from the signature at position `_pos` in a densely packed signatures bytes array.**\n\n\u003e Based on [OpenZeppelin's ECRecovery](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol)\n\nInputs\n\n| **type** | **name** | **description** |\n|-|-|-|\n| *bytes* | _signatures | The signatures bytes array |\n| *uint256* | _pos | The position of the signature in the bytes array (0 indexed) |\n\n\n## *function* toEthPersonalSignedMessageHash\n\nSignatureUtils.toEthPersonalSignedMessageHash(_msg) `pure` `d8a40f6b`\n\n**Converts a byte array to a personal signed message hash (result of `web3.personal.sign(...)`) by concatenating its length.**\n\n\nInputs\n\n| **type** | **name** | **description** |\n|-|-|-|\n| *bytes* | _msg | The bytes array to encrypt |\n\n\n## *function* toEthBytes32SignedMessageHash\n\nSignatureUtils.toEthBytes32SignedMessageHash(_msg) `pure` `e5990d20`\n\n**Converts a bytes32 to an signed message hash.**\n\n\nInputs\n\n| **type** | **name** | **description** |\n|-|-|-|\n| *bytes32* | _msg | The bytes32 message (i.e. keccak256 result) to encrypt |\n\n\n## *function* uintToString\n\nSignatureUtils.uintToString(v) `pure` `e9395679`\n\n**Converts a uint to its decimal string representation.**\n\n\nInputs\n\n| **type** | **name** | **description** |\n|-|-|-|\n| *uint256* | v | The uint to convert |\n\n\n## *function* recoverAddresses\n\nSignatureUtils.recoverAddresses(_hash, _signatures) `pure` `f0c8e969`\n\n**Recovers an array of addresses using a message hash and a signatures bytes array.**\n\n\nInputs\n\n| **type** | **name** | **description** |\n|-|-|-|\n| *bytes32* | _hash | The signed message hash |\n| *bytes* | _signatures | The signatures bytes array |\n\n\n---","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsys%2Fsolidity-sigutils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdsys%2Fsolidity-sigutils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsys%2Fsolidity-sigutils/lists"}