Skip to content

Commit

Permalink
Randomize context on creation
Browse files Browse the repository at this point in the history
If a context is created and not randomized then it is susceptible to
sidechannel attacks (quoting what I've read).

Currently it is easy for users to mis-use our API because they may not
know that `randomize()` should be called.

We can better assist users by making APIs that are hard to mis-use.

If the `rand` feature is enabled we can optimistically call `randomize`
when creating a context as we do for the global context.

Also, add documentation highlighting the benefit of using the `rand`
feature.

Resolves: #225
  • Loading branch information
tcharding committed Jan 25, 2022
1 parent 6b51575 commit 8b4ec1b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
26 changes: 20 additions & 6 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,38 +166,52 @@ mod alloc_only {
}

impl<C: Context> Secp256k1<C> {
/// Lets you create a context in a generic manner(sign/verify/all)
/// Lets you create a context in a generic manner(sign/verify/all).
///
/// If the `rand` feature is enabled we randomize the context using `thread_rng`.
#[allow(unused_mut)] // Unused when `rand` feature is not enabled.
pub fn gen_new() -> Secp256k1<C> {
#[cfg(target_arch = "wasm32")]
ffi::types::sanity_checks_for_wasm();

let size = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) };
let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
let ptr = unsafe {alloc::alloc(layout)};
Secp256k1 {
let mut secp = Secp256k1 {
ctx: unsafe { ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS) },
phantom: PhantomData,
size,
}
};

#[cfg(feature = "rand")]
secp.randomize(&mut rand::thread_rng());

secp
}
}

impl Secp256k1<All> {
/// Creates a new Secp256k1 context with all capabilities
/// Creates a new Secp256k1 context with all capabilities.
///
/// If the `rand` feature is enabled we randomize the context using `thread_rng`.
pub fn new() -> Secp256k1<All> {
Secp256k1::gen_new()
}
}

impl Secp256k1<SignOnly> {
/// Creates a new Secp256k1 context that can only be used for signing
/// Creates a new Secp256k1 context that can only be used for signing.
///
/// If the `rand` feature is enabled we randomize the context using `thread_rng`.
pub fn signing_only() -> Secp256k1<SignOnly> {
Secp256k1::gen_new()
}
}

impl Secp256k1<VerifyOnly> {
/// Creates a new Secp256k1 context that can only be used for verification
/// Creates a new Secp256k1 context that can only be used for verification.
///
/// If the `rand` feature is enabled we randomize the context using `thread_rng`.
pub fn verification_only() -> Secp256k1<VerifyOnly> {
Secp256k1::gen_new()
}
Expand Down
11 changes: 7 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
//! and its derivatives.
//!
//! To minimize dependencies, some functions are feature-gated. To generate
//! random keys or to re-randomize a context object, compile with the "rand"
//! feature. To de/serialize objects with serde, compile with "serde".
//! **Important**: `serde` encoding is **not** the same as consensus encoding!
//! random keys or to re-randomize a context object, compile with the `rand`
//! feature. If you are willing to use the `rand` dependency, we have enabled an
//! additional defense-in-depth sidechannel protection for our context objects,
//! which re-blinds certain operations on secret key data. To de/serialize
//! objects with serde, compile with "serde". **Important**: `serde` encoding is
//! **not** the same as consensus encoding!
//!
//! Where possible, the bindings use the Rust type system to ensure that
//! API usage errors are impossible. For example, the library uses context
Expand Down Expand Up @@ -117,7 +120,7 @@
//!
//! * `std` - use standard Rust library, enabled by default.
//! * `alloc` - use the `alloc` standard Rust library to provide heap allocations.
//! * `rand` - use `rand` library to provide random generator (e.g. to generate keys).
//! * `rand` - use `rand` library to provide randomness (e.g. to randomize contexts).
//! * `rand-std` - use `rand` library with its `std` feature enabled. (Implies `rand`.)
//! * `recovery` - enable functions that can compute the public key from signature.
//! * `lowmemory` - optimize the library for low-memory environments.
Expand Down

0 comments on commit 8b4ec1b

Please sign in to comment.