t_rust_less_lib/secrets_store/cipher/mod.rs
1use crate::memguard::SecretBytes;
2use crate::secrets_store_capnp::{block, KeyDerivationType, KeyType};
3
4use super::SecretStoreResult;
5
6#[cfg(feature = "openssl")]
7mod openssl_rsa_aes_gcm;
8mod rust_argon2id;
9#[cfg(feature = "rust_crypto")]
10mod rust_rsa_aes_gcm;
11mod rust_x25519_chacha20_poly1305;
12
13#[cfg(feature = "openssl")]
14pub use self::openssl_rsa_aes_gcm::OPEN_SSL_RSA_AES_GCM;
15pub use self::rust_argon2id::RUST_ARGON2_ID;
16#[cfg(feature = "rust_crypto")]
17pub use self::rust_rsa_aes_gcm::RUST_RSA_AES_GCM;
18pub use self::rust_x25519_chacha20_poly1305::RUST_X25519CHA_CHA20POLY1305;
19
20#[cfg(test)]
21mod fixture_tests;
22#[cfg(test)]
23mod tests;
24
25pub type PublicKey = Vec<u8>;
26pub type PrivateKey = SecretBytes;
27type PublicData = Vec<u8>;
28type PrivateData = SecretBytes;
29type SealKey = SecretBytes;
30
31/// Common interface of all cipher suites.
32///
33/// In this case "Chiper" does not refer to a single cipher but rather to a set of
34/// chiphers and methods used in combination to realize public/private key encryption
35/// on data with multiple recipients.
36///
37pub trait Cipher: Send + Sync {
38 /// Get the type identifier use inside the storage format.
39 fn key_type(&self) -> KeyType;
40
41 /// Get a displayable name of the cipher
42 fn name(&self) -> String;
43
44 /// Generate a new public-private key-pair.
45 ///
46 /// The cipher should decide by itself a suitable key-strength.
47 ///
48 fn generate_key_pair(&self) -> SecretStoreResult<(PublicKey, PrivateKey)>;
49
50 /// Get the required length of the seal key for the `seal_private_key` and `open_private_key` operation.
51 fn seal_key_length(&self) -> usize;
52
53 /// Get the minimal nonce length for all seal/open/encrypt/decrypt operations.
54 fn seal_min_nonce_length(&self) -> usize;
55
56 /// Seal a private key of this cipher suite.
57 ///
58 /// * `seal_key` the sealing key created by a key-derivation, ensured to have exactly `seal_key_length` bytes
59 /// * `nonce` random nonce to use, ensured to have at least `seal_min_nonce_length` bytes
60 /// * `private_key` the private key to seal, created by a `generate_key_pair` of this suite
61 ///
62 fn seal_private_key(
63 &self,
64 seal_key: &SealKey,
65 nonce: &[u8],
66 private_key: &PrivateKey,
67 ) -> SecretStoreResult<PublicData>;
68
69 /// Open a sealed private key of this cipher suite.
70 ///
71 /// * `seal_key` the sealing key created by a key-derivation, ensured to have exactly `seal_key_length` bytes
72 /// * `nonce` random nonce to use, ensured to have at least `seal_min_nonce_length` bytes
73 /// * `crypted_key` the encrypted bytes created by a `seal_private_key`
74 ///
75 fn open_private_key(&self, seal_key: &SealKey, nonce: &[u8], crypted_key: &[u8]) -> SecretStoreResult<PrivateKey>;
76
77 /// Encrypt arbitrary data for a set of recipients.
78 ///
79 /// * `recipients` list of recipients allowed to access/decrypt the data. It has to be
80 /// ensured that each recipient contains a public-key compatible with this suite.
81 /// * `data` the data to encrypt
82 /// * `header_builder` reference to the builder creating the encapsulating data-block for
83 /// storage
84 ///
85 fn encrypt(
86 &self,
87 recipients: &[(&str, PublicKey)],
88 data: &PrivateData,
89 header_builder: block::header::Builder,
90 ) -> SecretStoreResult<PublicData>;
91
92 /// Decrypt data for a user
93 ///
94 /// * `user` the user accessing/decrypting the data. It has to be ensured that the user
95 /// contains a private-key compatible with this suite and is part of the recipient list
96 /// of the data.
97 /// * `header` reference to the header of the stored data-block.
98 /// * `crypted` the encrypted data
99 ///
100 fn decrypt(
101 &self,
102 user: (&str, &PrivateKey),
103 header: block::header::Reader,
104 crypted: &[u8],
105 ) -> SecretStoreResult<PrivateData>;
106
107 fn find_matching_header<'a>(
108 &self,
109 headers: &capnp::struct_list::Reader<'a, block::header::Owned>,
110 ) -> SecretStoreResult<Option<block::header::Reader<'a>>> {
111 for header in headers.iter() {
112 if header.get_type()? == self.key_type() {
113 return Ok(Some(header));
114 }
115 }
116 Ok(None)
117 }
118}
119
120/// Common interface for a key-derivation method.
121///
122/// An implmentation of KeyDerivation is used to derive the seal-key of a Cipher.
123///
124/// Each method may have multiple presets for internal parameters that have to be adjusted to
125/// common CPU power and use-case. Each preset is identified by a simple number.
126///
127pub trait KeyDerivation: Send + Sync {
128 /// Get the key derivation type of the implmenetation.
129 fn key_derivation_type(&self) -> KeyDerivationType;
130
131 /// Get the default preset to use (for new keys).
132 fn default_preset(&self) -> u8;
133
134 /// Get the minmal length of a nonce for key-derivation.
135 fn min_nonce_len(&self) -> usize;
136
137 /// Derive a seal-key from a passphrase.
138 ///
139 /// * `passphrase` provided by the user
140 /// * `preset` key-derivation preset to use
141 /// * `nonce` random nonce to use, ensured to have at least `min_nonce_len` bytes
142 /// * `key_length` the required key-length of the seal-key. The output must have exactly
143 /// this length.
144 ///
145 fn derive(&self, passphrase: &SecretBytes, preset: u8, nonce: &[u8], key_length: usize)
146 -> SecretStoreResult<SealKey>;
147}