Skip to main content

onepass_seed/
lib.rs

1//! This crate implements arbitrary deterministic secret generation from a fixed seed password.
2//!
3//! The core, basic idea here is that a password schema should be enumerable: e.g. the schema
4//! `[a-z]` generates 26 different passwords, the first one is `'a'`, and the last is `'z'`. So
5//! then if we can count the size of the universe of passwords generated by a schema, then we can
6//! use a cryptographically secure pseudorandom number generator to sample it based on a
7//! deterministic secret, yielding a deterministic output.
8//!
9//! The other main piece of this password generation scheme entails securely deriving a per-site
10//! secret from a single seed password, thereby stretching one secret into an arbitrary number of
11//! secrets. We do this by taking a [password hash][0] of the seed password against a salt that
12//! consists of the full derivation parameters for the site in question; e.g. the site URL,
13//! username, and the schema from which the password is generated. Any changes to the derivation
14//! should therefore result in securely different secrets, meaning that generally a compromised
15//! site password should reveal no information about either the seed password or other site
16//! passwords.
17//!
18//! Combining these ideas then, usage of this library collapses the state for a password manager
19//! from `O(n)` secret state, where n is the number of sites for which a user has passwords, to
20//! `O(1)` secret state (the seed) plus `O(n)` non-secret state (the public site derivation
21//! parameters.) This makes migration much easier and safer than with traditional password
22//! managers; a user may simply upload or copy their site derivation info and write down or
23//! memorize their seed password.
24//!
25//! A lot of this crate, then, is about canonical serialization of site parameters and schemas such
26//! that derivation paths may be deterministically re-derived from configuration. E.g. we normalize
27//! URLs and we specify a canonical formatting of password schemas.
28//!
29//! This scheme is designed to be user-extensible; crate users may add their own custom secret
30//! generators to extend this library into other domains. This is done via
31//! <code>[Generator]</code>s. A `Generator` may extend a password schema with specific extra
32//! configuration, e.g. a hash of a word list, to ensure that derivations that are different
33//! produce uncorrelated passwords.
34//!
35//! The derivation parameters saved per-site are the (mandatory) URL, an optional username, the
36//! password schema, and a nonce (called the “increment” in this crate.) The purpose of the nonce
37//! is to make it easy to rotate a site password if one is ever compromised, or to comply with
38//! rotation policies; simply incrementing the nonce should yield an uncorrelated, new password for
39//! that site from the same seed.
40//!
41//! ```no_run
42//! use onepass_seed::site::Site;
43//! # use secrecy::ExposeSecret;
44//! let site = Site::new("google.com", None, "{words:4:-}", 0).unwrap();
45//! let pw = site.password("seedpass").unwrap();
46//! assert_eq!("jaywalker-diffused-verse-abdominal", pw.expose_secret());
47//! ```
48//!
49//! For more information on the schema language see <code>[Expr]</code>.
50//!
51//! [0]: https://en.wikipedia.org/wiki/Bcrypt
52//! [Generator]: expr::Generator
53//! [Expr]: expr::Expr
54
55mod crypto;
56pub mod dict;
57pub mod expr;
58mod macros;
59pub mod site;
60pub mod url;
61
62pub use crypto_bigint::U256;
63pub use secrecy::{ExposeSecret, ExposeSecretMut, SecretBox, SecretString};