Skip to content

Commit

Permalink
feat(identity): make rand optional
Browse files Browse the repository at this point in the history
Some restricted environments lack proper random source, and `getrandom` crate fails to compile.  However, random sources is needed only for random key generation which is not always required.

This change introduces `rand` feature flag that is gate to all the functionality that requires `rand` crate.

Pull-Request: #4349.
  • Loading branch information
monoid committed Oct 18, 2023
1 parent c442df8 commit 17c166a
Show file tree
Hide file tree
Showing 30 changed files with 63 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ libp2p-dns = { version = "0.40.1", path = "transports/dns" }
libp2p-floodsub = { version = "0.43.0", path = "protocols/floodsub" }
libp2p-gossipsub = { version = "0.45.2", path = "protocols/gossipsub" }
libp2p-identify = { version = "0.43.1", path = "protocols/identify" }
libp2p-identity = { version = "0.2.6" }
libp2p-identity = { version = "0.2.7" }
libp2p-kad = { version = "0.44.6", path = "protocols/kad" }
libp2p-mdns = { version = "0.44.0", path = "protocols/mdns" }
libp2p-memory-connection-limits = { version = "0.1.0", path = "misc/memory-connection-limits" }
Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ libp2p-mplex = { path = "../muxers/mplex" } # Using `path` he
libp2p-noise = { path = "../transports/noise" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing.
multihash = { workspace = true, features = ["arb"] }
quickcheck = { workspace = true }
libp2p-identity = { workspace = true, features = ["ed25519"] }
libp2p-identity = { workspace = true, features = ["ed25519", "rand"] }

[features]
serde = ["multihash/serde-codec", "dep:serde", "libp2p-identity/serde"]
Expand Down
6 changes: 6 additions & 0 deletions identity/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.2.7

- Add `rand` feature to gate methods requiring a random number generator, enabling use in restricted environments (e.g. smartcontracts).
This feature is not enabled by default.
See [PR 4349](https://github.com/libp2p/rust-libp2p/pull/4349).

## 0.2.6

- Make `PeerId::to_bytes` and `PeerId::to_base58` take `self` by value to follow Rust convention of `Copy` types.
Expand Down
13 changes: 7 additions & 6 deletions identity/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "libp2p-identity"
version = "0.2.6"
version = "0.2.7"
edition = "2021"
description = "Data structures and algorithms for identifying peers in libp2p."
rust-version = { workspace = true }
Expand All @@ -14,7 +14,7 @@ categories = ["cryptography"]
[dependencies]
asn1_der = { version = "0.7.6", optional = true }
bs58 = { version = "0.5.0", optional = true }
ed25519-dalek = { version = "2.0", optional = true, features = ["rand_core"] }
ed25519-dalek = { version = "2.0", optional = true }
hkdf = { version = "0.12.3", optional = true }
libsecp256k1 = { version = "0.7.0", optional = true }
log = "0.4"
Expand All @@ -33,11 +33,12 @@ zeroize = { version = "1.6", optional = true }
ring = { version = "0.16.9", features = [ "alloc", "std"], default-features = false, optional = true }

[features]
secp256k1 = ["dep:libsecp256k1", "dep:asn1_der", "dep:rand", "dep:sha2", "dep:hkdf", "dep:zeroize"]
ecdsa = ["dep:p256", "dep:rand", "dep:void", "dep:zeroize", "dep:sec1", "dep:sha2", "dep:hkdf"]
secp256k1 = ["dep:libsecp256k1", "dep:asn1_der", "dep:sha2", "dep:hkdf", "dep:zeroize"]
ecdsa = ["dep:p256", "dep:void", "dep:zeroize", "dep:sec1", "dep:sha2", "dep:hkdf"]
rsa = ["dep:ring", "dep:asn1_der", "dep:rand", "dep:zeroize"]
ed25519 = ["dep:ed25519-dalek", "dep:rand", "dep:zeroize", "dep:sha2", "dep:hkdf"]
peerid = ["dep:multihash", "dep:bs58", "dep:rand", "dep:thiserror", "dep:sha2", "dep:hkdf" ]
ed25519 = ["dep:ed25519-dalek", "dep:zeroize", "dep:sha2", "dep:hkdf"]
peerid = ["dep:multihash", "dep:bs58", "dep:thiserror", "dep:sha2", "dep:hkdf"]
rand = ["dep:rand", "ed25519-dalek?/rand_core"]

[dev-dependencies]
quickcheck = { workspace = true }
Expand Down
2 changes: 2 additions & 0 deletions identity/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub struct Keypair {

impl Keypair {
/// Generate a new random ECDSA keypair.
#[cfg(feature = "rand")]
pub fn generate() -> Keypair {
Keypair::from(SecretKey::generate())
}
Expand Down Expand Up @@ -265,6 +266,7 @@ mod tests {
use super::*;

#[test]
#[cfg(feature = "rand")]
fn sign_verify() {
let pair = Keypair::generate();
let pk = pair.public();
Expand Down
5 changes: 5 additions & 0 deletions identity/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub struct Keypair(ed25519::SigningKey);

impl Keypair {
/// Generate a new random Ed25519 keypair.
#[cfg(feature = "rand")]
pub fn generate() -> Keypair {
Keypair::from(SecretKey::generate())
}
Expand Down Expand Up @@ -181,6 +182,7 @@ impl fmt::Debug for SecretKey {

impl SecretKey {
/// Generate a new Ed25519 secret key.
#[cfg(feature = "rand")]
pub fn generate() -> SecretKey {
let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng);
SecretKey(signing.to_bytes())
Expand Down Expand Up @@ -213,6 +215,7 @@ mod tests {
}

#[test]
#[cfg(feature = "rand")]
fn ed25519_keypair_encode_decode() {
fn prop() -> bool {
let kp1 = Keypair::generate();
Expand All @@ -224,6 +227,7 @@ mod tests {
}

#[test]
#[cfg(feature = "rand")]
fn ed25519_keypair_from_secret() {
fn prop() -> bool {
let kp1 = Keypair::generate();
Expand All @@ -235,6 +239,7 @@ mod tests {
}

#[test]
#[cfg(feature = "rand")]
fn ed25519_signature() {
let kp = Keypair::generate();
let pk = kp.public();
Expand Down
13 changes: 6 additions & 7 deletions identity/src/keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,23 @@ enum KeyPairInner {

impl Keypair {
/// Generate a new Ed25519 keypair.
#[cfg(feature = "ed25519")]
#[cfg(all(feature = "ed25519", feature = "rand"))]
pub fn generate_ed25519() -> Keypair {
Keypair {
keypair: KeyPairInner::Ed25519(ed25519::Keypair::generate()),
}
}

/// Generate a new Secp256k1 keypair.
#[cfg(feature = "secp256k1")]
#[cfg(all(feature = "secp256k1", feature = "rand"))]
pub fn generate_secp256k1() -> Keypair {
Keypair {
keypair: KeyPairInner::Secp256k1(secp256k1::Keypair::generate()),
}
}

/// Generate a new ECDSA keypair.
#[cfg(feature = "ecdsa")]
#[cfg(all(feature = "ecdsa", feature = "rand"))]
pub fn generate_ecdsa() -> Keypair {
Keypair {
keypair: KeyPairInner::Ecdsa(ecdsa::Keypair::generate()),
Expand Down Expand Up @@ -352,7 +352,6 @@ impl Keypair {
/// ```
/// # fn main() {
/// # use libp2p_identity as identity;
///
/// let key = identity::Keypair::generate_ed25519();
///
/// let new_key = key.derive_secret(b"my encryption key").expect("can derive secret for ed25519");
Expand Down Expand Up @@ -926,7 +925,7 @@ mod tests {
}

#[test]
#[cfg(feature = "ed25519")]
#[cfg(all(feature = "ed25519", feature = "rand"))]
fn test_publickey_from_ed25519_public_key() {
let pubkey = Keypair::generate_ed25519().public();
let ed25519_pubkey = pubkey
Expand All @@ -941,7 +940,7 @@ mod tests {
}

#[test]
#[cfg(feature = "secp256k1")]
#[cfg(all(feature = "secp256k1", feature = "rand"))]
fn test_publickey_from_secp256k1_public_key() {
let pubkey = Keypair::generate_secp256k1().public();
let secp256k1_pubkey = pubkey
Expand All @@ -955,7 +954,7 @@ mod tests {
}

#[test]
#[cfg(feature = "ecdsa")]
#[cfg(all(feature = "ecdsa", feature = "rand"))]
fn test_publickey_from_ecdsa_public_key() {
let pubkey = Keypair::generate_ecdsa().public();
let ecdsa_pubkey = pubkey.clone().try_into_ecdsa().expect("A ecdsa keypair");
Expand Down
7 changes: 5 additions & 2 deletions identity/src/peer_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#[cfg(feature = "rand")]
use rand::Rng;
use sha2::Digest as _;
use std::{convert::TryFrom, fmt, str::FromStr};
Expand Down Expand Up @@ -101,6 +102,7 @@ impl PeerId {
/// Generates a random peer ID from a cryptographically secure PRNG.
///
/// This is useful for randomly walking on a DHT, or for testing purposes.
#[cfg(feature = "rand")]
pub fn random() -> PeerId {
let peer_id = rand::thread_rng().gen::<[u8; 32]>();
PeerId {
Expand Down Expand Up @@ -247,22 +249,23 @@ mod tests {
use super::*;

#[test]
#[cfg(feature = "ed25519")]
#[cfg(all(feature = "ed25519", feature = "rand"))]
fn peer_id_into_bytes_then_from_bytes() {
let peer_id = crate::Keypair::generate_ed25519().public().to_peer_id();
let second = PeerId::from_bytes(&peer_id.to_bytes()).unwrap();
assert_eq!(peer_id, second);
}

#[test]
#[cfg(feature = "ed25519")]
#[cfg(all(feature = "ed25519", feature = "rand"))]
fn peer_id_to_base58_then_back() {
let peer_id = crate::Keypair::generate_ed25519().public().to_peer_id();
let second: PeerId = peer_id.to_base58().parse().unwrap();
assert_eq!(peer_id, second);
}

#[test]
#[cfg(feature = "rand")]
fn random_peer_id_is_valid() {
for _ in 0..5000 {
let peer_id = PeerId::random();
Expand Down
3 changes: 3 additions & 0 deletions identity/src/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub struct Keypair {

impl Keypair {
/// Generate a new sec256k1 `Keypair`.
#[cfg(feature = "rand")]
pub fn generate() -> Keypair {
Keypair::from(SecretKey::generate())
}
Expand Down Expand Up @@ -88,6 +89,7 @@ impl fmt::Debug for SecretKey {

impl SecretKey {
/// Generate a new random Secp256k1 secret key.
#[cfg(feature = "rand")]
pub fn generate() -> SecretKey {
SecretKey(libsecp256k1::SecretKey::random(&mut rand::thread_rng()))
}
Expand Down Expand Up @@ -226,6 +228,7 @@ mod tests {
use super::*;

#[test]
#[cfg(feature = "rand")]
fn secp256k1_secret_from_bytes() {
let sk1 = SecretKey::generate();
let mut sk_bytes = [0; 32];
Expand Down
5 changes: 5 additions & 0 deletions libp2p/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
See `libp2p::SwarmBuilder` docs on how to use the new builder.
Also see [PR 4120].

- Update `libp2p-identity` version to 0.2.6.
Under the hood, we feature-flagged `libp2p-identity`'s `rand` dependency but it is enabled by default when using `libp2p`.
See [PR 4349].

[PR 3679]: https://github.com/libp2p/rust-libp2p/pull/3679
[PR 4120]: https://github.com/libp2p/rust-libp2p/pull/4120
[PR 4349]: https://github.com/libp2p/rust-libp2p/pull/4349

## 0.52.3

Expand Down
2 changes: 1 addition & 1 deletion libp2p/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ libp2p-dcutr = { workspace = true, optional = true }
libp2p-floodsub = { workspace = true, optional = true }
libp2p-gossipsub = { workspace = true, optional = true }
libp2p-identify = { workspace = true, optional = true }
libp2p-identity = { workspace = true }
libp2p-identity = { workspace = true, features = ["rand"] }
libp2p-kad = { workspace = true, optional = true }
libp2p-metrics = { workspace = true, optional = true }
libp2p-noise = { workspace = true, optional = true }
Expand Down
3 changes: 3 additions & 0 deletions misc/metrics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ libp2p-swarm = { workspace = true }
once_cell = "1.18.0"
prometheus-client = { version = "0.21.2"}

[dev-dependencies]
libp2p-identity = { workspace = true, features = ["rand"] }

# Passing arguments to the docsrs builder in order to properly document cfg's.
# More information: https://docs.rs/about/builds#cross-compiling
[package.metadata.docs.rs]
Expand Down
1 change: 1 addition & 0 deletions muxers/mplex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async-std = { version = "1.7.0", features = ["attributes"] }
criterion = "0.5"
env_logger = "0.10"
futures = "0.3"
libp2p-identity = { workspace = true, features = ["rand"] }
libp2p-muxer-test-harness = { path = "../test-harness" }
libp2p-plaintext = { workspace = true }
libp2p-tcp = { workspace = true, features = ["async-io"] }
Expand Down
2 changes: 1 addition & 1 deletion protocols/gossipsub/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ getrandom = "0.2.9"
hex_fmt = "0.3.0"
instant = "0.1.12"
libp2p-core = { workspace = true }
libp2p-identity = { workspace = true }
libp2p-identity = { workspace = true, features = ["rand"] }
libp2p-swarm = { workspace = true }
log = "0.4.20"
quick-protobuf = "0.8"
Expand Down
2 changes: 1 addition & 1 deletion protocols/kad/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ libp2p-core = { workspace = true }
libp2p-swarm = { workspace = true }
quick-protobuf = "0.8"
quick-protobuf-codec = { workspace = true }
libp2p-identity = { workspace = true }
libp2p-identity = { workspace = true, features = ["rand"] }
rand = "0.8"
sha2 = "0.10.8"
smallvec = "1.11.1"
Expand Down
2 changes: 1 addition & 1 deletion protocols/perf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ futures = "0.3.28"
instant = "0.1.12"
libp2p-core = { workspace = true }
libp2p-dns = { workspace = true, features = ["tokio"] }
libp2p-identity = { workspace = true }
libp2p-identity = { workspace = true, features = ["rand"] }
libp2p-tls = { workspace = true }
libp2p-quic = { workspace = true, features = ["tokio"] }
libp2p-request-response = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions protocols/relay/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void = "1"

[dev-dependencies]
env_logger = "0.10.0"
libp2p-identity = { workspace = true, features = ["rand"] }
libp2p-ping = { workspace = true }
libp2p-plaintext = { workspace = true }
libp2p-swarm = { workspace = true, features = ["macros", "async-std"] }
Expand Down
2 changes: 1 addition & 1 deletion swarm-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"]
[dependencies]
async-trait = "0.1.73"
libp2p-core = { workspace = true }
libp2p-identity = { workspace = true }
libp2p-identity = { workspace = true, features = ["rand"] }
libp2p-plaintext = { workspace = true }
libp2p-swarm = { workspace = true, features = ["async-std"] }
libp2p-tcp = { workspace = true, features = ["async-io"] }
Expand Down
1 change: 1 addition & 0 deletions transports/dns/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ smallvec = "1.11.1"

[dev-dependencies]
env_logger = "0.10"
libp2p-identity = { workspace = true, features = ["rand"] }
tokio-crate = { package = "tokio", version = "1.0", default-features = false, features = ["rt", "time"] }
async-std-crate = { package = "async-std", version = "1.6" }

Expand Down
1 change: 1 addition & 0 deletions transports/noise/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ snow = { version = "0.9.2", features = ["default-resolver"], default-features =
env_logger = "0.10.0"
futures_ringbuf = "0.4.0"
quickcheck = { workspace = true }
libp2p-identity = { workspace = true, features = ["rand"] }

# Passing arguments to the docsrs builder in order to properly document cfg's.
# More information: https://docs.rs/about/builds#cross-compiling
Expand Down
2 changes: 1 addition & 1 deletion transports/plaintext/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] }

[dev-dependencies]
env_logger = "0.10.0"
libp2p-identity = { workspace = true, features = ["ed25519"] }
libp2p-identity = { workspace = true, features = ["ed25519", "rand"] }
quickcheck = { workspace = true }
rand = "0.8"
futures_ringbuf = "0.4.0"
Expand Down
2 changes: 1 addition & 1 deletion transports/pnet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pin-project = "1.1.3"

[dev-dependencies]
libp2p-core = { workspace = true }
libp2p-identity = { workspace = true, features = ["ed25519", "rsa", "ecdsa","secp256k1"] }
libp2p-identity = { workspace = true, features = ["ed25519", "rsa", "ecdsa","secp256k1", "rand"] }
libp2p-noise = { workspace = true }
libp2p-swarm = { workspace = true, features = ["tokio"] }
libp2p-tcp = { workspace = true, features = ["tokio"] }
Expand Down
1 change: 1 addition & 0 deletions transports/quic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ rustc-args = ["--cfg", "docsrs"]
[dev-dependencies]
async-std = { version = "1.12.0", features = ["attributes"] }
env_logger = "0.10.0"
libp2p-identity = { workspace = true, features = ["rand"] }
libp2p-muxer-test-harness = { path = "../../muxers/test-harness" }
libp2p-noise = { workspace = true }
libp2p-tcp = { workspace = true, features = ["async-io"] }
Expand Down
1 change: 1 addition & 0 deletions transports/tcp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async-io = ["dep:async-io", "if-watch/smol"]

[dev-dependencies]
async-std = { version = "1.6.5", features = ["attributes"] }
libp2p-identity = { workspace = true, features = ["rand"] }
tokio = { version = "1.33.0", default-features = false, features = ["full"] }
env_logger = "0.10.0"

Expand Down
2 changes: 1 addition & 1 deletion transports/tls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ features = ["dangerous_configuration"] # Must enable this to allow for custom ve
hex = "0.4.3"
hex-literal = "0.4.1"
libp2p-core = { workspace = true }
libp2p-identity = { workspace = true, features = ["ed25519", "rsa", "secp256k1", "ecdsa"] }
libp2p-identity = { workspace = true, features = ["ed25519", "rsa", "secp256k1", "ecdsa", "rand"] }
libp2p-swarm = { workspace = true, features = ["tokio"] }
libp2p-yamux = { workspace = true }
tokio = { version = "1.33.0", features = ["full"] }
Expand Down
Loading

0 comments on commit 17c166a

Please sign in to comment.