{"id":13546158,"url":"https://github.com/stouset/secrets","last_synced_at":"2025-04-04T08:06:27.642Z","repository":{"id":24382164,"uuid":"27781870","full_name":"stouset/secrets","owner":"stouset","description":"Secure storage for cryptographic secrets in Rust","archived":false,"fork":false,"pushed_at":"2024-07-16T15:19:41.000Z","size":353,"stargazers_count":216,"open_issues_count":12,"forks_count":11,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-28T07:04:40.616Z","etag":null,"topics":["cryptographic-secrets","cryptography-tools","memory-management","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/stouset.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","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":"2014-12-09T19:01:41.000Z","updated_at":"2025-03-22T01:39:44.000Z","dependencies_parsed_at":"2024-11-29T22:17:00.483Z","dependency_job_id":null,"html_url":"https://github.com/stouset/secrets","commit_stats":{"total_commits":191,"total_committers":8,"mean_commits":23.875,"dds":0.04712041884816753,"last_synced_commit":"79d479afacd621decbd5cd986bd1f8bef49a83bd"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stouset%2Fsecrets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stouset%2Fsecrets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stouset%2Fsecrets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stouset%2Fsecrets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stouset","download_url":"https://codeload.github.com/stouset/secrets/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247142014,"owners_count":20890651,"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-secrets","cryptography-tools","memory-management","rust"],"created_at":"2024-08-01T12:00:32.659Z","updated_at":"2025-04-04T08:06:27.618Z","avatar_url":"https://github.com/stouset.png","language":"Rust","funding_links":[],"categories":["Cryptography","Rust"],"sub_categories":["Frameworks"],"readme":"secrets\n=======\n\n[![Build Status][badge-ci]][ci]\n\u003c!-- [![Test Coverage][badge-coverage]][coverage] --\u003e\n[![Cargo Crate][badge-package]][package]\n[![Docs][badge-docs]][docs]\n[![License][badge-license]][license]\n\n`secrets` is a library to help Rust programmers safely held cryptographic\nsecrets in memory.\n\nIt is mostly an ergonomic wrapper around the memory-protection utilities\nprovided by [libsodium].\n\nFixed-size buffers allocated on the stack gain the following protections:\n\n* [`mlock(2)`][mlock] is called on the underlying memory\n* the underlying memory is zeroed out when no longer in use\n* they are borrowed for their entire lifespan, so cannot be moved\n* they are compared in constant time\n* they are prevented from being printed by `Debug`\n* they are prevented from being `Clone`d\n\nFixed and variable-sized buffers can be allocated on the heap and gain\nthe following protections:\n\n* the underlying memory is protected from being read from or written to\n  with [`mprotect(2)`][mprotect] unless an active borrow is in scope\n* [`mlock(2)`][mlock] is called on the allocated memory\n* the underlying memory is zeroed out when no longer in use\n* overflows and underflows are detected using inaccessible guard pages,\n  causing an immediate segmentation fault and program termination\n* short underflows that write to memory are detected when memory is\n  freed using canaries, and will result in a segmentation fault and\n  program termination\n\nPanic Safety\n------------\n\nThis library is explicitly not panic-safe. To ensure the safety of\nprotected memory space, this library can and will panic if it is unable\nto enforce its advertised guarantees.\n\nSimilarly, this library will cause segmentation faults if (and only if)\nit detects certain safety violations. For example, this can happen if\na process attempts to directly read or write to the contents of memory\nthat hasn't been properly unlocked, or if canaries have been\noverwritten. This library has been written to ensure that such\nviolations should be impossible to cause through well-formed Rust, and\nso should only occur as a result of a security vulnerability.\n\nExamples\n--------\n\n### Example: generating cryptographic keys\n\n```rust\nSecret::\u003c[u8; 16]\u003e::random(|s| {\n    // use `s` as if it were a `\u0026mut [u8; 16]`\n    //\n    // the memory is `mlock(2)`ed and will be zeroed when this closure\n    // exits\n});\n```\n\n### Example: load a master key from disk and generate subkeys from it\n\n```rust\nuse std::fs::File;\nuse std::io::Read;\n\nuse libsodium_sys as sodium;\nuse secrets::SecretBox;\n\nconst KEY_LEN : usize = sodium::crypto_kdf_KEYBYTES     as _;\nconst CTX_LEN : usize = sodium::crypto_kdf_CONTEXTBYTES as _;\n\nconst CONTEXT : \u0026[u8; CTX_LEN] = b\"example\\0\";\n\nfn derive_subkey(\n    key:       \u0026[u8; KEY_LEN],\n    context:   \u0026[u8; CTX_LEN],\n    subkey_id: u64,\n    subkey:    \u0026mut [u8],\n) {\n    unsafe {\n        libsodium_sys::crypto_kdf_derive_from_key(\n            subkey.as_mut_ptr(),\n            subkey.len(),\n            subkey_id,\n            context.as_ptr().cast(),\n            key.as_ptr()\n        );\n    }\n}\n\nlet master_key = SecretBox::\u003c[u8; KEY_LEN]\u003e::try_new(|mut s| {\n    File::open(\"example/master_key/key\")?.read_exact(s)\n})?;\n\nlet subkey_0 = SecretBox::\u003c[u8; 16]\u003e::new(|mut s| {\n    derive_subkey(\u0026master_key.borrow(), CONTEXT, 0, s);\n});\n\nlet subkey_1 = SecretBox::\u003c[u8; 16]\u003e::new(|mut s| {\n    derive_subkey(\u0026master_key.borrow(), CONTEXT, 1, s);\n});\n\nassert_ne!(\n    subkey_0.borrow(),\n    subkey_1.borrow(),\n);\n```\n\n### Example: securely storing a decrypted ciphertext in memory\n\n```rust\nuse std::fs::File;\nuse std::io::Read;\n\nuse libsodium_sys as sodium;\nuse secrets::{SecretBox, SecretVec};\n\nconst KEY_LEN   : usize = sodium::crypto_secretbox_KEYBYTES   as _;\nconst NONCE_LEN : usize = sodium::crypto_secretbox_NONCEBYTES as _;\nconst MAC_LEN   : usize = sodium::crypto_secretbox_MACBYTES   as _;\n\nlet mut key        = SecretBox::\u003c[u8; KEY_LEN]\u003e::zero();\nlet mut nonce      = [0; NONCE_LEN];\nlet mut ciphertext = Vec::new();\n\nFile::open(\"example/decrypted_ciphertext/key\")?\n    .read_exact(key.borrow_mut().as_mut())?;\n\nFile::open(\"example/decrypted_ciphertext/nonce\")?\n    .read_exact(\u0026mut nonce)?;\n\nFile::open(\"example/decrypted_ciphertext/ciphertext\")?\n    .read_to_end(\u0026mut ciphertext)?;\n\nlet plaintext = SecretVec::\u003cu8\u003e::new(ciphertext.len() - MAC_LEN, |mut s| {\n    if -1 == unsafe {\n        sodium::crypto_secretbox_open_easy(\n            s.as_mut_ptr(),\n            ciphertext.as_ptr(),\n            ciphertext.len() as _,\n            nonce.as_ptr(),\n            key.borrow().as_ptr(),\n        )\n    } {\n        panic!(\"failed to authenticate ciphertext during decryption\");\n    }\n});\n\nassert_eq!(\n    *b\"attack at dawn\",\n    *plaintext.borrow(),\n);\n```\n\nLicense\n-------\n\nLicensed under either of\n\n * [Apache License, Version 2.0](LICENSE-APACHE)\n * [MIT license](LICENSE-MIT)\n\nat your option.\n\n[ci]:       https://github.com/stouset/secrets/actions/workflows/test.yml\n\u003c!-- [coverage]: https://coveralls.io/github/stouset/secrets --\u003e\n[docs]:     https://stouset.github.io/secrets\n[license]:  https://github.com/stouset/secrets/blob/master/LICENSE\n[package]:  https://crates.io/crates/secrets\n\n[badge-ci]:       https://github.com/stouset/secrets/actions/workflows/test.yml/badge.svg\n\u003c!-- [badge-coverage]: https://coveralls.io/repos/github/stouset/secrets/badge.svg --\u003e\n[badge-docs]:     https://docs.rs/secrets/badge.svg\n[badge-license]:  https://img.shields.io/crates/l/secrets.svg\n[badge-package]:  https://img.shields.io/crates/v/secrets.svg\n\n[libsodium]: https://download.libsodium.org/doc/memory_management\n[mlock]:     http://man7.org/linux/man-pages/man2/mlock.2.html\n[mprotect]:  http://man7.org/linux/man-pages/man2/mprotect.2.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstouset%2Fsecrets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstouset%2Fsecrets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstouset%2Fsecrets/lists"}