{"id":17939402,"url":"https://github.com/libitx/curvy","last_synced_at":"2025-03-24T10:32:08.330Z","repository":{"id":41252589,"uuid":"344533650","full_name":"libitx/curvy","owner":"libitx","description":"Signatures and Bitcoin flavoured crypto written in pure Elixir.","archived":false,"fork":false,"pushed_at":"2023-02-13T11:10:19.000Z","size":787,"stargazers_count":26,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-14T05:32:59.754Z","etag":null,"topics":["bitcoin","bsv","ecdsa","rfc-6979","secp256k1"],"latest_commit_sha":null,"homepage":"https://hexdocs.pm/curvy","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/libitx.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":"2021-03-04T16:11:49.000Z","updated_at":"2024-06-20T22:53:35.000Z","dependencies_parsed_at":"2023-02-09T13:00:55.195Z","dependency_job_id":null,"html_url":"https://github.com/libitx/curvy","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/libitx%2Fcurvy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libitx%2Fcurvy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libitx%2Fcurvy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libitx%2Fcurvy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/libitx","download_url":"https://codeload.github.com/libitx/curvy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245252426,"owners_count":20585060,"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":["bitcoin","bsv","ecdsa","rfc-6979","secp256k1"],"created_at":"2024-10-29T00:07:08.360Z","updated_at":"2025-03-24T10:32:07.970Z","avatar_url":"https://github.com/libitx.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Curvy\n\n![Curvy](https://raw.githubusercontent.com/libitx/curvy/main/media/poster.png)\n\n![Hex.pm](https://img.shields.io/hexpm/v/curvy?color=informational)\n![License](https://img.shields.io/github/license/libitx/curvy?color=informational)\n![Build Status](https://img.shields.io/github/actions/workflow/status/libitx/curvy/elixir.yml?branch=main)\n\nSignatures and Bitcoin flavoured crypto written in pure Elixir. Curvy is an implementation of `secp256k1`, an elliptic curve that can be used in signature schemes, asymmetric encryption and ECDH shared secrets.\n\n## Highlights\n\n* Pure Elixir implementation of `secp256k1` - no external dependencies\n* Fast ECDSA cryptography using Jacobian Point mathematics\n* Supports deterministic ECDSA signatures as per [RFC 6979](https://tools.ietf.org/html/rfc6979)\n* Securely generate random ECDSA keypairs\n* Compute ECDH shared secrets\n\n## Installation\n\nThe package can be installed by adding `curvy` to your list of dependencies in `mix.exs`.\n\n```elixir\ndef deps do\n  [\n    {:curvy, \"~\u003e 0.3\"}\n  ]\nend\n```\n\n## Usage\n\nFor further examples, refer to the [full documentation](https://hexdocs.pm/curvy).\n\n### 1. Key generation\n\nCreate random ECDSA keypairs.\n\n```elixir\niex\u003e key = Curvy.generate_key()\n%Curvy.Key{\n  crv: :secp256k1,\n  point: %Curvy.Point{},\n  private_key: \u003c\u003c\u003e\u003e\n}\n```\n\nECDSA Keypairs can by converted to public and private key binaries.\n\n```elixir\niex\u003e Curvy.Key.to_privkey(key)\n\u003c\u003cprivkey::binary-size(32)\u003e\u003e\n\niex\u003e Curvy.Key.to_pubkey(key)\n\u003c\u003cprivkey::binary-size(33)\u003e\u003e\n\niex\u003e Curvy.Key.to_pubkey(key, compressed: false)\n\u003c\u003cprivkey::binary-size(65)\u003e\u003e\n```\n\n### 2. Sign messages\n\nSign arbitrary messages with a private key. Signatures are deterministic as per [RFC 6979](https://tools.ietf.org/html/rfc6979).\n\n```elixir\niex\u003e sig = Curvy.sign(\"hello\", key)\n\u003c\u003csig::binary-size(71)\u003e\u003e\n\niex\u003e sig = Curvy.sign(\"hello\", key, compact: true)\n\u003c\u003csig::binary-size(65)\u003e\u003e\n\niex\u003e sig = Curvy.sign(\"hello\", key, compact: true, encoding: :base64)\n\"IEnXUDXZ3aghwXaq1zu9ax2zJj7N+O4gGREmWBmrldwrIb9B7QuicjwPrrv3ocPpxYO7uCxcw+DR/FcHR9b/YjM=\"\n```\n\n### 3. Verify signatures\n\nVerify a signature against the message and a public key.\n\n```elixir\niex\u003e sig = Curvy.verify(sig, \"hello\", key)\ntrue\n\niex\u003e sig = Curvy.verify(sig, \"hello\", wrongkey)\nfalse\n\n# Returns :error if the signature cannot be decoded\niex\u003e sig = Curvy.verify(\"notasig\", \"hello\", key)\n:error\n```\n\n### 4. Recover the public key from a signature\n\nIt's possible to recover the public key from a compact signature when given\nwith the signed message.\n\n```elixir\niex\u003e sig = Curvy.sign(\"hello\", key, compact: true)\niex\u003e recovered = Curvy.recover_key(sig, \"hello\")\niex\u003e recovered.point == key.point\ntrue\n```\n\nThe same can be done with DER encoded signatures if the recovery ID is known.\n\n```elixir\niex\u003e {sig, recovery_id} = Curvy.sign(\"hello\", key, recovery: true)\niex\u003e recovered = Curvy.recover_key(sig, \"hello\", recovery_id: recovery_id)\niex\u003e recovered.point == key.point\ntrue\n```\n\n### 5. ECDH shared secrets\n\nECDH shared secrets are computed by multiplying a public key with a private\nkey. The operation yields the same result in both directions.\n\n```elixir\niex\u003e s1 = Curvy.get_shared_secret(key1, key2)\niex\u003e s2 = Curvy.get_shared_secret(key2, key1)\niex\u003e s1 == s2\ntrue\n```\n\n\n\nFor more examples, refer to the [full documentation](https://hexdocs.pm/curvy).\n\n## Disclaimer\n\nThe are many warnings that you should never try to implement well-known (and known to be secure) crypto algorithms yourself. Well guess what, that's exactly what I've done here. I am **not** a cryptographer nor a mathmetician. Proceed at your own risk. If you're after the most performant and battle tested Bitcoin library, use the [`libsecp256k1`](https://hex.pm/packages/libsecp256k1) NIF bindings.\n\nThis library offers a simpler and smaller interface for common functionality. Being writting purely in Elixir without any dependencies, it is a lighter-weight option without the compilation complexities NIF bindings may bring.\n\nI am grateful to the authors of the following open source libraries I have referred to extensively in creating this library:\n\n* [noble-secp256k1](https://github.com/paulmillr/noble-secp256k1) - JS\n* [starbank-ecdsa](https://github.com/starkbank/ecdsa-elixir) - Elixir\n* [bsv](https://github.com/moneybutton/bsv) - JS\n\n## License\n\nCurvy is open source and released under the [Apache-2 License](https://github.com/libitx/curvy/blob/master/LICENSE).\n\n© Copyright 2021 [Chronos Labs Ltd](https://www.chronoslabs.net).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibitx%2Fcurvy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flibitx%2Fcurvy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibitx%2Fcurvy/lists"}