You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
stack-encrypt: derive ValueFrame's constant-time PartialEq once vitaminc can compare a Vec<u8> #1542
stack-encrypt is the Rust engine in this repository that encrypts each value under its own key. Its dynamic API passes each value as a ValueFrame. A ValueFrame stores one value's bytes in vitaminc's transport format, called a frame.
vitaminc is CipherStash's Rust library of cryptographic building blocks. Its vitaminc-protected crate has wrapper types for secrets. A wrapper wipes its secret when it is dropped. Equatable<T> is the wrapper for a secret that can be compared, in constant time.
Problem
ValueFrame stores its frame in an Equatable<Protected<Vec<u8>>>, since #1501. But Equatable cannot compare a Vec<u8> yet. vitaminc-protected 0.9.1 has no ConstantTimeEq impl for Vec<u8>. The trait is sealed, so this crate cannot add one. cipherstash/vitaminc#602 adds it.
Until then, ValueFrame's PartialEq is written by hand, in packages/stack-encrypt/src/dynamic/value_frame.rs. It reads both frames' bytes and compares them with TimingSafeEq for [u8]. That impl calls subtle. The comparison is constant-time and safe. It is a workaround, though: it reads the bytes itself, where Equatable would compare them without the crate reading them.
Move the vitaminc-protected pin to the new version in the root Cargo.toml and in packages/stack-encrypt/fuzz/Cargo.toml. Then regenerate each lockfile that cargo metadata --locked refuses. Check the root, both Go guests, EQL, the three fuzz crates, and the EQL timing harness's ctgen.
In value_frame.rs, delete the hand-written impl PartialEq for ValueFrame and its comment, and derive it: #[derive(OpaqueDebug, PartialEq)]. Keep the doc that says what equal means, on the struct or on the derive.
Keep the four tests in the equality module of value_frame.rs. They must pass unchanged: equal frames, a one-byte difference, different lengths, and 34u32 against 34u64.
Check that the three doc examples that compare frames still pass. They are in value_frame.rs (module docs), record.rs (record::encrypt), and kind.rs (dynamic::read).
Update the CHANGELOG entry that names the workaround.
Activity
Equatable<Protected<Vec<u8>>>cannot be compared, becauseConstantTimeEqhas noVec<u8>impl vitaminc#602