How to use two different versions of a crate in a Rust project?

⚓ Rust    📅 2025-09-03    👤 surdeus    👁️ 2      

surdeus

Suppose my project needs to use two crates, call them crate A and crate B. Also both crates have a dependency on crate C. But crate A depends on a version of crate C that isn't compatible with crate B, while create B depends on a version of crate C that isn't compatible with crate A.

How do I get around this? :thinking:

(This is a follow up question to: How to use the RustCrypto "ansi-x963-kdf" crate?)

Example

Here is an example project:

#![no_std]

use p256::{ecdsa::{Signature, VerifyingKey, signature::DigestVerifier}, elliptic_curve::generic_array::GenericArray};
use sha2::{Digest, Sha256};

pub fn derive_shared_key_x963<const N: usize>(secret: &[u8], shared_info: &[u8]) -> [u8; N] {
    let mut key = [0u8; N];
    ansi_x963_kdf::derive_key_into::<Sha256>(secret, shared_info, &mut key).unwrap();
    key
}

pub fn verify_signature(verifying_key: &VerifyingKey, message_data: &[u8], signature_data: &[u8]) {
    let signature = Signature::from_bytes(GenericArray::from_slice(signature_data));
    let mut sha256 = Sha256::default();
    sha256.update(message_data);
    verifying_key.verify_digest(sha256, &signature);
}

Option 1

The first function will work with:

[dependencies]
ansi-x963-kdf = "0.0.1"
p256 = { version = "0.13.2", default-features = false, features = [ "ecdsa", "ecdh" ] }
sha2 = { version = "=0.11.0-pre.4", default-features = false  }

...but then the second function has error:

error[E0277]: the trait bound `VerifyingKey<NistP256>: DigestVerifier<CoreWrapper<...>, _>` is not satisfied
  --> src/lib.rs:24:33
   |
24 |     verifying_key.verify_digest(sha256, &signature);
   |                   ------------- ^^^^^^ unsatisfied trait bound
   |                   |
   |                   required by a bound introduced by this call
   |
   = help: the trait `DigestVerifier<sha2::digest::core_api::CoreWrapper<sha2::digest::core_api::CtVariableCoreWrapper<Sha256VarCore, UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>, OidSha256>>, _>` is not implemented for `ecdsa::verifying::VerifyingKey<NistP256>`
   = help: the following other types implement trait `DigestVerifier<D, S>`:
             `ecdsa::verifying::VerifyingKey<C>` implements `DigestVerifier<D, ecdsa::Signature<C>>`
             `ecdsa::verifying::VerifyingKey<C>` implements `DigestVerifier<D, ecdsa::der::Signature<C>>`
   = note: the full name for the type has been written to '/home/user/src/digitalkey-rust/rust/libs/kdf-x963/target/debug/deps/kdf_x963-db1c3a7fe774ea72.long-type-18000074307032300888.txt'
   = note: consider using `--verbose` to print the full type name to the console

Option 2

The second function will work with:

[dependencies]
ansi-x963-kdf = "0.0.1"
p256 = { version = "0.13.2", default-features = false, features = [ "ecdsa", "ecdh" ] }
sha2 = "0.10.9"

...but then the first function has error:

error[E0277]: the trait bound `CoreWrapper<CtVariableCoreWrapper<..., ..., ...>>: FixedOutputReset` is not satisfied
   --> src/lib.rs:16:38
    |
16  |     ansi_x963_kdf::derive_key_into::<Sha256>(secret, shared_info, &mut key).unwrap();
    |                                      ^^^^^^ the trait `digest::FixedOutputReset` is not implemented for `CoreWrapper<CtVariableCoreWrapper<Sha256VarCore, UInt<..., ...>, ...>>`
    |
note: there are multiple different versions of crate `digest` in the dependency graph
   --> /home/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.11.0-pre.9/src/lib.rs:107:1
    |
107 | pub trait FixedOutputReset: FixedOutput + Reset {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is the required trait
    |
   ::: src/lib.rs:11:5
    |
11  | use p256::{ecdsa::{Signature, VerifyingKey, signature::DigestVerifier}, elliptic_curve::generic_array::GenericArray};
    |     ---- one version of crate `digest` used here, as a dependency of crate `elliptic_curve`
...
16  |     ansi_x963_kdf::derive_key_into::<Sha256>(secret, shared_info, &mut key).unwrap();
    |     ------------- one version of crate `digest` used here, as a dependency of crate `ansi_x963_kdf`
    |
   ::: /home/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/core_api/wrapper.rs:24:1
    |
24  | pub struct CoreWrapper<T>
    | ------------------------- this type doesn't implement the required trait
...
266 | pub trait CoreProxy: sealed::Sealed {
    | ----------------------------------- this is the found trait
    |
   ::: /home/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.11.0-pre.9/src/core_api/wrapper.rs:31:1
    |
31  | pub struct CoreWrapper<T: BufferKindUser> {
    | ----------------------------------------- this type implements the required trait
    = note: two types coming from two different versions of the same crate are different types even if they look the same
    = help: you can use `cargo tree` to explore your dependency tree
note: required by a bound in `derive_key_into`
   --> /home/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ansi-x963-kdf-0.0.1/src/lib.rs:21:17
    |
19  | pub fn derive_key_into<D>(secret: &[u8], shared_info: &[u8], key: &mut [u8]) -> Result<(), Error>
    |        --------------- required by a bound in this function
20  | where
21  |     D: Digest + FixedOutputReset,
    |                 ^^^^^^^^^^^^^^^^ required by this bound in `derive_key_into`
    = note: the full name for the type has been written to '/home/user/src/digitalkey-rust/rust/libs/kdf-x963/target/debug/deps/kdf_x963-10e496880e04491b.long-type-1674101330059690571.txt'
    = note: consider using `--verbose` to print the full type name to the console

Is there any way how I can get both functions to work in the same project ???

It seems I would need to use two different versions of the sha2 crate at the same time :confused:

Thank you!

5 posts - 2 participants

Read full topic

🏷️ Rust_feed