{"id":19269569,"url":"https://github.com/status-im/doubleratchet","last_synced_at":"2025-04-21T20:32:59.336Z","repository":{"id":37952873,"uuid":"95424399","full_name":"status-im/doubleratchet","owner":"status-im","description":"The Double Ratchet Algorithm implementation in Go","archived":false,"fork":false,"pushed_at":"2020-12-06T15:31:41.000Z","size":102,"stargazers_count":109,"open_issues_count":2,"forks_count":14,"subscribers_count":10,"default_branch":"develop","last_synced_at":"2024-06-18T15:39:49.497Z","etag":null,"topics":["cryptographic-algorithms","golang","golang-library"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"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/status-im.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":"2017-06-26T08:17:59.000Z","updated_at":"2024-05-01T23:27:42.000Z","dependencies_parsed_at":"2022-09-03T20:33:31.141Z","dependency_job_id":null,"html_url":"https://github.com/status-im/doubleratchet","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/status-im%2Fdoubleratchet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/status-im%2Fdoubleratchet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/status-im%2Fdoubleratchet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/status-im%2Fdoubleratchet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/status-im","download_url":"https://codeload.github.com/status-im/doubleratchet/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223877724,"owners_count":17218615,"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":["cryptographic-algorithms","golang","golang-library"],"created_at":"2024-11-09T20:20:34.506Z","updated_at":"2024-11-09T20:20:35.058Z","avatar_url":"https://github.com/status-im.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# doubleratchet\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/status-im/doubleratchet)](https://goreportcard.com/report/github.com/status-im/doubleratchet)\n[![Build Status](https://travis-ci.org/status-im/doubleratchet.svg?branch=master)](https://travis-ci.org/status-im/doubleratchet)\n[![Coverage Status](https://coveralls.io/repos/github/status-im/doubleratchet/badge.svg?branch=master)](https://coveralls.io/github/status-im/doubleratchet?branch=master)\n[![GoDoc](https://godoc.org/github.com/status-im/doubleratchet?status.svg)](https://godoc.org/github.com/status-im/doubleratchet)\n\n[The Double Ratchet Algorithm](https://whispersystems.org/docs/specifications/doubleratchet) is used\nby two parties to exchange encrypted messages based on a shared secret key. Typically the parties\nwill use some key agreement protocol (such as X3DH) to agree on the shared secret key.\nFollowing this, the parties will use the Double Ratchet to send and receive encrypted messages.\n\nThe parties derive new keys for every Double Ratchet message so that earlier keys cannot be calculated\nfrom later ones. The parties also send Diffie-Hellman public values attached to their messages.\nThe results of Diffie-Hellman calculations are mixed into the derived keys so that later keys cannot\nbe calculated from earlier ones. These properties gives some protection to earlier or later encrypted \nmessages in case of a compromise of a party's keys.\n\n## Project status\n\nThe library is in beta version and ready for integration into production projects with care.\nLet me know if you face any problems or have any questions or suggestions.\n\n## Implementation notes\n\n### The Double Ratchet logic\n\n1. No more than 1000 messages can be skipped in a single chain.\n1. Skipped messages from a single ratchet step are deleted after 100 ratchet steps.\n1. Both parties' sending and receiving chains are initialized with the shared key so that both\nof them could message each other from the very beginning.\n\n### Cryptographic primitives \n\n1. **GENERATE_DH():** Curve25519\n1. **KDF_RK(rk, dh_out):** HKDF with SHA-256\n1. **KDF_CK(ck):** HMAC with SHA-256 and constant inputs\n1. **ENCRYPT(mk, pt, associated_data):** AES-256-CTR with HMAC-SHA-256 and IV derived alongside an encryption key\n\n## Installation\n\n    go get github.com/status-im/doubleratchet\n\nthen `cd` into the project directory and install dependencies:\n\n    glide up\n    \nIf `glide` is not installed, [install it](https://github.com/Masterminds/glide).\n\n## Usage\n\n### Basic usage example\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/status-im/doubleratchet\"\n)\n\nfunc main() {\n\t// The shared key both parties have already agreed upon before the communication.\n\tsk := [32]byte{\n\t\t0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20,\n\t\t0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a,\n\t\t0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb,\n\t\t0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40,\n\t}\n\n\t// Diffie-Hellman key pair generated by one of the parties during key exchange or\n\t// by any other means. The public key MUST be sent to another party for initialization\n\t// before the communication begins.\n\tkeyPair, err := doubleratchet.DefaultCrypto{}.GenerateDH()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Bob MUST be created with the shared secret and a DH key pair.\n\tbob, err := doubleratchet.New([]byte(\"bob-session-id\"), sk, keyPair, nil)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Alice MUST be created with the shared secret and Bob's public key.\n\talice, err := doubleratchet.NewWithRemoteKey([]byte(\"alice-session-id\"), sk, keyPair.PublicKey(), nil)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Alice can now encrypt messages under the Double Ratchet session.\n\tm, err := alice.RatchetEncrypt([]byte(\"Hi Bob!\"), nil)\n\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Which Bob can decrypt.\n\tplaintext, err := bob.RatchetDecrypt(m, nil)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Println(string(plaintext))\n}\n```\n\n### Options\n\nAdditional options can be passed to constructors to customize the algorithm behavior:\n\n```go\ndoubleratchet.New(\n    sk, keyPair,\n    \n    // Your own cryptography supplement implementing doubleratchet.Crypto.\n    WithCrypto(c),\n    \n    // Custom storage for skipped keys implementing doubleratchet.KeysStorage.\n    WithKeysStorage(ks),\n    \n    // The maximum number of skipped keys. Error will be raised in an attempt to store more keys\n    // in a single chain while decrypting.\n    WithMaxSkip(1200),\n    \n    // The number of Diffie-Hellman ratchet steps skipped keys will be stored.\n    WithMaxKeep(90),\n)\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstatus-im%2Fdoubleratchet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstatus-im%2Fdoubleratchet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstatus-im%2Fdoubleratchet/lists"}