-
Notifications
You must be signed in to change notification settings - Fork 219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix!: refactor CipherSeed
, zeroize, and fix key derivation
#4860
fix!: refactor CipherSeed
, zeroize, and fix key derivation
#4860
Conversation
9a01ad9
to
0f02318
Compare
0f02318
to
fc39869
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - some minor comments
utACK |
CipherSeed
, zeroize, and fix key derivationCipherSeed
, zeroize, and fix key derivation
Nice. Please add a note on how existing seed phrases and wallets are affected |
Done. If you wanted an interesting test of the versioning system, we could bump the |
@@ -113,12 +116,13 @@ pub const CIPHER_SEED_MAC_BYTES: usize = 5; | |||
pub struct CipherSeed { | |||
version: u8, | |||
birthday: u16, | |||
entropy: [u8; CIPHER_SEED_ENTROPY_BYTES], | |||
salt: [u8; CIPHER_SEED_SALT_BYTES], | |||
entropy: Vec<u8>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should we replace fixed size arrays to Vec
's, in this case ? I personally think it is expressive to know in advance the size of both entropy
and salt
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a Vec
made it easier to handle zeroizing of secret data (due to heap storage), and also should keep the structure more general in case of future updates, where data sizes could change based on version. I could easily imagine a future where all size constants are part of a version-dependent lookup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm certainly open to changing back to arrays for now, but it seems like this requires much more careful zeroizing wrappers to account for copies/moves, which seems like a footgun to avoid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Box<[u8; CIPHER_SEED_SALT_BYTES]>
is also an option as that allocates a fixed size array on the heap and you move a pointer (Box) around, not the data. But happy to keep it as a vec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanations @AaronFeickert. I would say that @sdbondi suggestion is the most explicit. I am also happy to use Vec
here, it is probably not worth spending time on refactoring it it, as of now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The refactoring was pretty straightforward, so I went ahead and switched from Vec<u8>
to Box<[u8]>
for clarity on sizes. For some reason Zeroizing
didn't like Box<[u8]>
, so there's one spot where we do Zeroizing<[u8]>
and then create the Box
later (this is in case of MAC failure, as @sdbondi pointed out elsewhere); it didn't complain when we #[derive(Zeroize)]
on Box<[u8]>
though, which is odd...
Very cool ! Thanks for the detailed explanations as well. utACK |
2420ae4
to
894a424
Compare
894a424
to
e8a9a39
Compare
Description --- Updates `argon2` for the gRPC and wallet use cases. Improves handling of keys and secret data. Fixes [issue 4882](#4882). Motivation and Context --- [Issue 4882](#4882) notes that different versions of `argon2` are used throughout the codebase. The newer minor version `0.4` changes the API significantly, and the older version `0.2` is [no longer supported](https://crates.io/crates/argon2/0.2.0). Additionally, gRPC and wallet implementations use the default parameter set from the crate, which is not in line with the [OWASP recommendations](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id) that we use elsewhere in the key manager. Further, it's recommended that a [specific function](https://docs.rs/argon2/0.4.1/argon2/struct.Argon2.html#method.hash_password_into) be used when performing KDF functionality, as this binds the parameter set into the output. While not a major security issue, it's worth updating to this function where appropriate. Finally, secret data is kept in memory in many places through the codebase, and this area is no exception. As part of good practice, we should try to zeroize such data wherever possible. This PR addresses these issues. It updates the gRPC and wallet `argon2` versions to `0.4` (the key manager is addressed in [PR 4860](#4860) and makes the necessary API changes. It updates the parameter set to be consistent with the linked recommendations. It also adds some improved handling of secret data (but does not do so comprehensively, limiting the scope to the updated code). How Has This Been Tested? --- Existing tests pass. BREAKING: This changes how wallet passphrase-based hashes and keys are derived.
Description
Significantly refactors
CipherSeed
for clarity, zeroizes internal secrets, fixes key derivation, and verifies MACs in constant time. Does not zeroize external passphrases, which should be done separately. Fixes issue 4859.Motivation and Context
As noted in issue 4859,
CipherSeed
MAC keys are derived incorrectly; in fact, the same main key is derived twice to obtain the MAC key and encryption key used forCipherSeed
encryption. This work refactors for several goals:subtle
functionality.How Has This Been Tested?
Existing tests, as the external API does not change. Manual inspection that keys are now derived correctly.
BREAKING CHANGE: Existing (version 0) seeds no longer work. Only version 1 seeds are valid.