Skip to content

Commit 08f16f2

Browse files
authored
ctutils: add subtle migration guide (#1465)
Adds a section to the toplevel documentation to assist users who have existing code which uses `subtle` and would like to migrate to `ctutils`. It covers the mappings of the trait/method names and includes various small caveats that can potentially trip one up.
1 parent ae493bf commit 08f16f2

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

ctutils/src/lib.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,45 @@
7979
//!
8080
//! This makes it possible to use `ctutils` in a codebase where other dependencies are using
8181
//! `subtle`.
82+
//!
83+
//! # [`subtle`] migration guide
84+
//!
85+
//! This library presents an API which is largely the same shape as `subtle` and amenable to mostly
86+
//! mechanical find-and-replace updates. Using the above `subtle` interop, you can also migrate
87+
//! incrementally by converting `ctutils::Choice` <=> `subtle::Choice` and `ctutils::CtOption`
88+
//! <=> `subtle::CtOption`.
89+
//!
90+
//! The following substitutions can be used to perform the migration:
91+
//!
92+
//! 1. `subtle` => `ctutils`
93+
//! 2. `ConstantTimeEq` => `CtEq`, `ConstantTimeGreater` => `CtGt`, `ConstantTimeLess` => `CtLt`.
94+
//! - These all use the same `ct_eq`/`ct_gt`/`ct_lt` method names as `subtle` with the same type
95+
//! signatures, so only the trait names need to be changed.
96+
//! 3. `ConditionallySelectable` => `CtSelect`, `conditional_select` => `ct_select`.
97+
//! - Note that `ct_select` has a slightly different type signature in that it accepts `&self`
98+
//! as the LHS argument. This needs to be changed in the `impl` blocks, but call sites are
99+
//! compatible if you update the method name alone because it's valid "fully qualified syntax".
100+
//! Changing them from `T::conditional_select(&a, &b, choice)` => `a.ct_select(&b, choice)`
101+
//! may still be nice for brevity.
102+
//! - `conditional_assign` => `CtAssign::ct_assign`: this one will require some manual work as
103+
//! this method has been split out of `ConditionallySelectable` into its own `CtAssign` trait,
104+
//! which makes it possible to impl on DSTs like slices which can't be returned from a select
105+
//! operation because they're `!Sized`.
106+
//! 4. `ConditionallyNegatable` => `CtNeg`, `conditional_negate` => `ct_neg`
107+
//!
108+
//! ## `CtOption` notes
109+
//!
110+
//! A notable semantic change from `subtle` is combinators like `CtOption::map` no longer have a
111+
//! `Default` bound and will call the provided function with the contained value unconditionally.
112+
//!
113+
//! This means whatever value was provided at the time the `CtOption` was constructed now needs to
114+
//! uphold whatever invariants the provided function is expecting.
115+
//!
116+
//! Code which previously constructed a `CtOption` with an invalid inner value that worked with
117+
//! `subtle` because the `Default` value upheld these invariants might break when the provided
118+
//! function is now called with the invalid inner value.
119+
//!
120+
//! See also: [dalek-cryptography/subtle#63](https://github.com/dalek-cryptography/subtle/issues/63)
82121
83122
#[cfg(feature = "alloc")]
84123
extern crate alloc;

0 commit comments

Comments
 (0)