{"id":22281050,"url":"https://github.com/fadeevab/cocoon","last_synced_at":"2025-05-08T00:20:41.772Z","repository":{"id":38201018,"uuid":"263054668","full_name":"fadeevab/cocoon","owner":"fadeevab","description":"Simple and reliable secure storage with strong encryption and format validation.","archived":false,"fork":false,"pushed_at":"2024-09-02T10:59:58.000Z","size":116,"stargazers_count":75,"open_issues_count":0,"forks_count":14,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-29T16:19:49.509Z","etag":null,"topics":["cryptography","encryption","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/fadeevab.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-11T13:44:43.000Z","updated_at":"2025-04-24T03:13:37.000Z","dependencies_parsed_at":"2023-10-24T10:35:42.806Z","dependency_job_id":"b66fa0e8-cfd2-4d4d-82e7-f887e0df2f0c","html_url":"https://github.com/fadeevab/cocoon","commit_stats":{"total_commits":102,"total_committers":3,"mean_commits":34.0,"dds":0.02941176470588236,"last_synced_commit":"cb4fa2054db84c39fde471b821e90089a307a083"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fadeevab%2Fcocoon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fadeevab%2Fcocoon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fadeevab%2Fcocoon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fadeevab%2Fcocoon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fadeevab","download_url":"https://codeload.github.com/fadeevab/cocoon/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252974247,"owners_count":21834229,"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":["cryptography","encryption","rust"],"created_at":"2024-12-03T16:13:09.482Z","updated_at":"2025-05-08T00:20:41.743Z","avatar_url":"https://github.com/fadeevab.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Cocoon](https://github.com/fadeevab/cocoon/workflows/Cocoon/badge.svg)](https://github.com/fadeevab/cocoon)\n[![crates.io](https://img.shields.io/crates/v/cocoon.svg)](https://crates.io/crates/cocoon)\n[![docs.rs](https://docs.rs/cocoon/badge.svg)](https://docs.rs/cocoon/)\n[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/fadeevab/cocoon/LICENSE)\n[![coverage](https://coveralls.io/repos/github/fadeevab/cocoon/badge.svg?branch=main)](https://coveralls.io/github/fadeevab/cocoon?branch=main)\n\n# Cocoon\n\n\u003cimg alt=\"Cocoon format\" src=\"https://github.com/fadeevab/cocoon/raw/main/images/cocoon_format.svg\" /\u003e\n\n`MiniCocoon` and `Cocoon` are protected containers to wrap sensitive data with strong\n[encryption](#cryptography) and format validation. A format of `MiniCocoon` and `Cocoon`\nis developed for the following practical cases:\n\n1. As an _encrypted file format_ to organize simple secure storage:\n   1. Key store.\n   2. Password store.\n   3. Sensitive data store.\n2. For _encrypted data transfer_:\n   * As a secure in-memory container.\n\n`Cocoon` is developed with security in mind. It aims to do only one thing and do it\nflawlessly. It has a minimal set of dependencies and a minimalist design to simplify control over\nsecurity aspects. It's a pure Rust implementation, and all dependencies are pure Rust\npackages with disabled default features.\n\n# Use Case\n\nWhenever you need to transmit and store data securely you reinvent the wheel: you have to\ntake care of how to encrypt data properly, how to handle randomly generated buffers,\nthen how to get data back, parse, and decrypt. Instead, you can use `MiniCocoon`\nand `Cocoon`.\n\n# Basic Usage\n\n## 📌 Wrap/Unwrap\n\nOne party wraps private data into a container using `MiniCocoon::wrap`.\nAnother party (or the same one, or whoever knows the key) unwraps data\nout of the container using `MiniCocoon::unwrap`.\n\n`MiniCocoon` is preferred against `Cocoon` in a case of simple data encryption\nbecause it generates a container with a smaller header without version control, and also\nit allows to wrap data sequentially (wrap, wrap, wrap!) without performance drop\nbecause of KDF calculation.\n```rust\nlet mut cocoon = MiniCocoon::from_key(b\"0123456789abcdef0123456789abcdef\", \u0026[0; 32]);\n\nlet wrapped = cocoon.wrap(b\"my secret data\")?;\nassert_ne!(\u0026wrapped, b\"my secret data\");\n\nlet unwrapped = cocoon.unwrap(\u0026wrapped)?;\nassert_eq!(unwrapped, b\"my secret data\");\n```\n\n## 📌 Dump/Parse\n\nYou can store data to file. Put data into `Vec` container, the data is going to be\nencrypted _in place_ and stored in a file using the \"cocoon\" [format](#cocoon).\n\n`Cocoon` is preferred as a long-time data storage, it has an extended header with a magic\nnumber, options, and version control.\n```rust\nlet mut data = b\"my secret data\".to_vec();\nlet mut cocoon = Cocoon::new(b\"password\");\n\ncocoon.dump(data, \u0026mut file)?;\n\nlet data = cocoon.parse(\u0026mut file)?;\nassert_eq!(\u0026data, b\"my secret data\");\n```\n\n## 📌 Encrypt/Decrypt\n\nYou can encrypt data in place and avoid re-allocations. The method operates with a detached\nmeta-data (a container format prefix) in the array on the stack. It is suitable for \"`no_std`\"\nbuild and whenever you want to evade re-allocations of a huge amount of data. You have to care\nabout how to store and transfer a data length and a container prefix though.\n\nBoth `MiniCocoon` and `Cocoon` have the same API, but prefixes are of different sizes.\n`MiniCocoon` doesn't have the overhead of generating KDF on each encryption call, therefore\nit's recommended for simple sequential encryption/decryption operations.\n```rust\nlet mut data = \"my secret data\".to_owned().into_bytes();\nlet mut cocoon = MiniCocoon::from_key(b\"0123456789abcdef0123456789abcdef\", \u0026[0; 32]);\n\nlet detached_prefix = cocoon.encrypt(\u0026mut data)?;\nassert_ne!(data, b\"my secret data\");\n\ncocoon.decrypt(\u0026mut data, \u0026detached_prefix)?;\nassert_eq!(data, b\"my secret data\");\n```\n\n# Study Case\nYou implement a database of secrets that must be stored in an encrypted file using a user\npassword. There are a lot of ways how your database can be represented in memory and how\nit could be serialized. You handle these aspects on your own, e.g. you can use\n`HashMap` to manage data and use `borsh`, or `bincode`,\nto serialize the data. You can even compress a serialized buffer before encryption.\n\nIn the end, you use `Cocoon` to put the final image into an encrypted container.\n\n```rust\nuse borsh::{BorshDeserialize, BorshSerialize};\nuse cocoon::{Cocoon, Error};\n\nuse std::collections::HashMap;\nuse std::fs::File;\n\n// Your data can be represented in any way.\n#[derive(BorshDeserialize, BorshSerialize)]\nstruct Database {\n    inner: HashMap\u003cString, String\u003e,\n}\n\nfn main() -\u003e Result\u003c(), Error\u003e {\n    let mut file = File::create(\"target/test.db\")?;\n    let mut db = Database { inner: HashMap::new() };\n\n    // Over time you collect some kind of data.\n    db.inner.insert(\"my.email@example.com\".to_string(), \"eKPV$PM8TV5A2\".to_string());\n\n    // You can choose how to serialize data. Also, you can compress it.\n    let encoded = db.try_to_vec().unwrap();\n\n    // Finally, you want to store your data secretly.\n    // Supply some password to Cocoon: it can be any byte array, basically.\n    // Don't use a hard-coded password in real life!\n    // It could be a user-supplied password.\n    let mut cocoon = Cocoon::new(b\"secret password\");\n\n    // Dump the serialized database into a file as an encrypted container.\n    let container = cocoon.dump(encoded, \u0026mut file)?;\n\n    // Let's look at how to decrypt the container and parse it back.\n    let mut file = File::open(\"target/test.db\").unwrap();\n    let encoded = cocoon.parse(\u0026mut file).unwrap();\n    let decoded = Database::try_from_slice(\u0026encoded).unwrap();\n\n    Ok(())\n}\n```\n\n# Cryptography\n\n256-bit cryptography is chosen as a `Cocoon` baseline.\n\n| Cipher (AEAD)     | Key Derivation Function (KDF)    |\n|-------------------|----------------------------------|\n| Chacha20-Poly1305 | PBKDF2-SHA256: 100000 iterations |\n| AES256-GCM        |                                  |\n\n* Key: 256-bit.\n* Salt for KDF: random 128-bit + predefined part.\n* Nonce for encryption: random 96-bit.\n\nKey derivation parameters comply with NIST SP 800-132 recommendations (salt, iterations),\nand cipher parameters (key, nonce, length) fit requirements of a particular cipher.\nAEAD is chosen in order to authenticate encrypted data together with an unencrypted header.\n\n# Zeroization\n\nEncryption key is wrapped into zeroizing container\n(provided by `zeroize` crate), which means that the key is erased automatically once it is dropped.\n\n# How It Works\n\nSee more implementation details on\n[![docs.rs](https://docs.rs/cocoon/badge.svg)](https://docs.rs/cocoon/), e.g.\n1. the process of [container creation](https://docs.rs/cocoon/#container-creation),\n2. customizable [crate features](https://docs.rs/cocoon/#crate-features),\n3. and of course [API](https://docs.rs/cocoon/#cocoon).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffadeevab%2Fcocoon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffadeevab%2Fcocoon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffadeevab%2Fcocoon/lists"}