-
Notifications
You must be signed in to change notification settings - Fork 22
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
feat: improve hidden data handling #52
Conversation
Pretty cool ! LGTM |
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 not convinced this is the right approach.
There's some debate going on in another fork of this repo on the same topic that I'll copy over here, when I have a spare minute.
We'll get there though.
Significantly updated. The latest commit instead updates |
028240e
to
fe49469
Compare
fe49469
to
de35cc9
Compare
src/hidden.rs
Outdated
macro_rules! hidden_label { | ||
($name:ident) => { | ||
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] | ||
pub struct $name; | ||
|
||
impl HiddenLabel for $name {} | ||
}; | ||
} |
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.
Something about the macro feels like an anti-pattern to me. From a usability perspective to have the marker trait applied I would want to throw it into derive
. The use of hidden_label!()
is offputting for a reason I can't quite put my finger on.
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 not a huge fan of the approach, and I wish there were a better way to do what we want (enforced type differentiation) in Rust without resorting to replicating boilerplate code in a way that's likely to be done wrong. For what it's worth, @jorgeantonio21 suggested replacing the whole macro construction with a const str
in the generic type definition, but Rust doesn't support it. I'm definitely open to a different approach if we can find one that works.
Possibly worth noting that a similar approach is used in both the new hashing and Schnorr signature APIs to enforce type differentiation and enable certain hash operations to do what we want.
src/hidden.rs
Outdated
// A default hidden type label; only use this if you're absolutely sure you don't care about type enforcement | ||
hidden_label!(DefaultHiddenLabel); | ||
|
||
/// Data that needs to be kept hidden, needs to be zeroized when it goes away, and is resistant to misuse |
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.
Perhaps add an example to docs. Something like
/// Data that needs to be kept hidden, needs to be zeroized when it goes away, and is resistant to misuse | |
/// Data that needs to be kept hidden, needs to be zeroized when it goes away, and is resistant to misuse. | |
/// | |
/// The following will throw a compile error: | |
/// | |
/// hidden_label!(MyFirstLabel); | |
/// hidden_label!(MySecondLabel); | |
/// | |
/// type HiddenType1 = Hidden<[u8; 3], MyFirstLabel>; | |
/// type HiddenType2 = Hidden<[u8; 3], MySecondLabel>; | |
/// | |
/// fn accept_only_hidden_type_2(hidden: HiddenType2) { | |
/// println!("My dear hidden type 2"); | |
/// } | |
/// | |
/// let hidden_1 = HiddenType1::hide([0u8, 1, 2]); | |
/// accept_only_hidden_type_2(hidden_1); |
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 am pretty satisfied with the current state. I left a few minor comments.
@brianp pointed out that the use of the hidden_label
macro is not clear for a developer without the right context, there might be a way to satisfy our goal of type enforcement in a simpler way.
Nonetheless, I consider having type enforcement is a very important feature to have.
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.
Everything we discussed was addressed, I am in favor of it.
LGTM
Can someone enable CI workflows, so we can check for any problems there? |
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 :)
Updated to address some implementation concerns that primarily concern derived traits and trait bounds:
This means we can now use the macro with types that don't support serialization or defaults, which can include even basic types like It also means that the |
Description --- Minor updates for a corresponding [change](tari-project/tari_utilities#52) to the `SafePassword` API. Motivation and Context --- A pending change in `tari_utilities` to the handling of sensitive data includes a new implementation of `SafePassword`. One change removes derived traits for equality testing in favor of equality testing on references to the underlying passphrase data. This work makes the minor but necessary changes to address this API change. How Has This Been Tested? --- Tests pass after applying the linked `tari_utilities` PR. Note that tests will pass using the current `SafePassword` API as well, as the dependency change PR restricts the API.
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.
Looks good. A few nits, and I suggest we remove serialisation support
} | ||
|
||
/// Provides access to the inner value (mutable). | ||
/// Reveal the hidden data as a mutable reference |
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.
Would be good to have a description on why this is safe, given the way Box
is treated by the compiler when dereferenced. Same for reveal
.
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.
From the analysis @CjS77 did on the compiled version, it's unclear precisely if/where this can go wrong. My understanding was that asterisk dereferencing of a Box<T>
can perform a move, but need not do so in all cases. One apparent way to avoid this may be to replace any asterisk dereferencing with explicit calls to <Box<T> as Deref>::deref
instead, but I have not tested this (and I'm not sure if the wrapped reference calls we use avoid this problem regardless).
All |
To mitigate dereference woes, added a new Since it's intended for keys, also implements You'd use it by defining a hidden type in this manner: Then you can use Comments welcome on this idea. |
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 think this is as good as we can make it for now.
It would be interesting to see some performance benchmarks for secret key and ECC operations based on this (Vec<u8>
) vs [u8; 32]
One day when #[sensitive]
attributes can be passed to LLVM (something that is being discussed but not on any roadmap afaict), we can come and revisit this approach
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, I left a minor comment. Let's also run cargo fmt
.
* fix: updates for SafePassword API change (#4927) Description --- Minor updates for a corresponding [change](tari-project/tari_utilities#52) to the `SafePassword` API. Motivation and Context --- A pending change in `tari_utilities` to the handling of sensitive data includes a new implementation of `SafePassword`. One change removes derived traits for equality testing in favor of equality testing on references to the underlying passphrase data. This work makes the minor but necessary changes to address this API change. How Has This Been Tested? --- Tests pass after applying the linked `tari_utilities` PR. Note that tests will pass using the current `SafePassword` API as well, as the dependency change PR restricts the API. * chore: remove unused methods (#4922) Delete some unused methods * v0.40.0 * fix: set wallet start scan height to birthday and not 0 (see issue #4807) (#4911) Description --- When wallet starts new UTXO scanning service it should start at the birthday. Currently, it starts at height 0. This PR addresses this issue Motivation and Context --- Addresses #4807. How Has This Been Tested? --- * chore: fix naming of ffi functions and comments (#4930) Description --- Fixing the comments of one function in the wallet FFI. Fixes the names of 4 functions in the wallet FFI. * chore: fix depreciated timestamp clippy (#4929) Description --- Fixes depreciated timestamp warnings * feat: implement validator node lmdb store * feat: add stateless vn reg utxo validation rules and merkle root * rename vn validaty period consensus constant * use commitment instead of block hash so that lmdb uses canonical ordering * DRY up vn_mmr calculation, add vn reg utxo validations * fix clippies * wallet: use amount from consensus constants for VN reg * adds validator node signature to common types This is to allow the validator node to use the same signature * remove commitment from signature for now * Remove unneeded validator node kernel feature * ad epoch_length to grpc consensus constants * fix epoch interval check and add test * reduce target time for igor * clippy * change shard key hash label Co-authored-by: Aaron Feickert <66188213+AaronFeickert@users.noreply.github.com> Co-authored-by: stringhandler <mikethetike@tari.com> Co-authored-by: jorgeantonio21 <matroid@outlook.com> Co-authored-by: SW van Heerden <swvheerden@gmail.com>
I wouldn't use this for elliptic curve |
Yep, will run a few more proof-of-concept tests locally to ensure this will meet our needs, and then format to make the linter happy. |
Updated to implement Would appreciate if someone can verify that you still can't dereference the underlying data. I ran into sizing errors while trying to do this. Also would like comment on whether the |
5a14d9b
to
ef3803a
Compare
Some data, like cryptographic key material or passwords, needs special handling. Such data typically should:
This PR updates the
Hidden
type to handle this kind of data in a generic way. Hidden types can be instantiated using any underlying type that implementsZeroize
and an optional differentiated type created by a macro that enforces context and prevents misuse.The hidden data is stored on the heap in a
Box
wrapper. This allows us to safely zeroize it on drop, and automatically prevents display and debug from revealing it unintentionally. Further, we only expose access to the data via immutable and mutable reference. The implementation supportsClone
for cases where we need it, but does not supportCopy
.We also update
SafePassword
to be an instantiation of the updatedHidden
type. This refactor is transparent to callers, as its existing API is unchanged.