There 3 classes are designed with your use case in mind:
All of them fit together to encrypt a password database.
-
Create
helps you choose encryption strength by timing the users system.
-
Key
takes the params from Create
with the users password and derives a unique key.
-
Kdf
is used to derive subkeys. This class produces the encryption keys used by SecretBox
or XChaCha20Poly1305Ietf
(recommended).
`
Password::Create
Helps you choose parameters. There are several strategies in choosing key strength. Some recommendations:
- Use fixed parameters after timing them on the slowest system likely to be used (easy)
- Let
Create
choose them based on a given time estimate. (easy)
- Display different values to the user letting them decide by using
Create
or copying one of the examples (harder)
When choosing max mem be sure you take multiple systems and other programs in to account. Don’t set it to the systems max memory. Maybe use the lesser of 1/4, 1/8 system memory with a max of 256M-1024M.
It’s ok to use the defaults. They have fairly conservative values.
Password::Key
Takes the password with the provided params and gives a high quality master key. Only use this key to derive subkeys. Never store it.
Password
can directly give you a Kdf
so you never need to touch this.
Kdf
Derives subkeys from a master key. Use this to create individual encryption keys for each file or possibly each database record.
If you encrypt your password database as a single file you probably need 1 subkey.
If you want different databases or each entry to have it’s own encryption key then you’ll need multiple subkeys.
Convenience methods exist to create CryptoBox
, Sign
or other Sodium
objects. Prefer these methods to using subkeys directly. It’s less effort.
Example
# First use - creating a password key and saving an initial database
pwkc = Sodium::Password::Key::Create.new
pwkc.tcost = 0.5 # Up to 1/2 second to create key.
kdf, params = pwkc.create_kdf password
save params for later
# use unique values for each file/record
# string portion must be 8 chars and may be a fixed value or possibly table name
# the int portion may be a fixed value for single file, db record id or other
cipher = kdf.aead_xchacha20poly_ietf "8charsub", 0
data = cipher.encrypt database.to_json
File.write("db", data)
# Loading a password database
pwkey = Sodium::Password::Key.from_params hash
kdf = pwkey.derive_kdf pass
cipher = kdf.aead_xchacha20poly_ietf "8charsub", 0
database = cipher.decrypt File.read("db").from_json
See examples for further information