From fba7c4c93aba5928fa060c2124471211a450a0d4 Mon Sep 17 00:00:00 2001 From: Adam Spofford <93943719+adamspofford-dfinity@users.noreply.github.com> Date: Mon, 7 Oct 2024 08:51:02 -0700 Subject: [PATCH] feat: Use `ed25519-consensus` instead of `ring` (#606) --- CHANGELOG.md | 1 + Cargo.lock | 27 +++++---- Cargo.toml | 3 +- ic-agent/Cargo.toml | 9 +-- ic-agent/src/agent/mod.rs | 8 +-- ic-agent/src/identity/basic.rs | 60 ++++++++++++++----- ic-agent/src/identity/delegated.rs | 6 +- ic-agent/src/identity/error.rs | 11 +++- ic-agent/src/lib.rs | 9 +-- ic-transport-types/src/lib.rs | 2 +- ic-utils/Cargo.toml | 5 +- ic-utils/src/call.rs | 19 +++--- ic-utils/src/canister.rs | 11 +--- .../src/interfaces/management_canister.rs | 2 +- icx/Cargo.toml | 3 +- icx/src/main.rs | 15 ++--- ref-tests/Cargo.toml | 3 +- ref-tests/src/utils.rs | 11 ++-- ref-tests/tests/integration.rs | 29 +++------ 19 files changed, 118 insertions(+), 116 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef23df17..bf11e762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +* Changed `BasicIdentity`'s implmentation from `ring` to `ed25519-consensus`. * Added `AgentBuilder::with_max_polling_time` to config the maximum time to wait for a response from the replica. * `DelegatedIdentity::new` now checks the delegation chain. The old behavior is available under `new_unchecked`. diff --git a/Cargo.lock b/Cargo.lock index 110e0cd2..ef4a2b5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1006,9 +1006,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http", @@ -1054,6 +1054,7 @@ dependencies = [ "backoff", "cached", "candid", + "der", "ecdsa", "ed25519-consensus", "elliptic-curve", @@ -1076,7 +1077,6 @@ dependencies = [ "rangemap", "reqwest", "ring", - "rustls-webpki", "sec1", "serde", "serde_bytes", @@ -1146,10 +1146,11 @@ version = "0.38.2" dependencies = [ "async-trait", "candid", + "ed25519-consensus", "futures-util", "ic-agent", "once_cell", - "ring", + "rand", "semver", "serde", "serde_bytes", @@ -1211,11 +1212,12 @@ dependencies = [ "candid", "candid_parser", "clap", + "ed25519-consensus", "hex", "humantime", "ic-agent", "ic-utils", - "ring", + "rand", "serde", "serde_json", "tokio", @@ -1929,13 +1931,14 @@ name = "ref-tests" version = "0.0.0" dependencies = [ "candid", + "ed25519-consensus", "ic-agent", "ic-certification", "ic-identity-hsm", "ic-utils", "k256", "p256", - "ring", + "rand", "serde", "serde_cbor", "sha2 0.10.8", @@ -2061,9 +2064,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ "once_cell", "ring", @@ -2085,15 +2088,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", diff --git a/Cargo.toml b/Cargo.toml index 02767256..effbf262 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,13 +30,14 @@ ic-certification = "2.2" candid = "0.10.1" candid_parser = "0.1.1" clap = "4.4.3" +ed25519-consensus = "2.1.0" futures-util = "0.3.21" hex = "0.4.3" k256 = "0.13.4" leb128 = "0.2.5" p256 = "0.13.2" +rand = "0.8.5" reqwest = { version = "0.12", default-features = false } -ring = "0.17.7" serde = "1.0.162" serde_bytes = "0.11.13" serde_cbor = "0.11.2" diff --git a/ic-agent/Cargo.toml b/ic-agent/Cargo.toml index c1de4d55..e6b4e47c 100644 --- a/ic-agent/Cargo.toml +++ b/ic-agent/Cargo.toml @@ -23,8 +23,9 @@ async-watch = { version = "0.3", optional = true } backoff = "0.4.0" cached = { version = "0.52", features = ["ahash"], default-features = false } candid = { workspace = true } +der = "0.7" ecdsa = "0.16" -ed25519-consensus = { version = "2" } +ed25519-consensus = { workspace = true } elliptic-curve = "0.13" futures-util = { workspace = true } hex = { workspace = true } @@ -38,9 +39,9 @@ p256 = { workspace = true, features = ["pem"] } leb128 = { workspace = true } pkcs8 = { version = "0.10.2", features = ["std"] } sec1 = { version = "0.7.2", features = ["pem"] } -rand = "0.8.5" +rand = { workspace = true } rangemap = "1.4" -ring = { workspace = true, features = ["std"] } +ring = { version = "0.17", optional = true } serde = { workspace = true, features = ["derive"] } serde_bytes = { workspace = true } serde_cbor = { workspace = true } @@ -65,7 +66,6 @@ optional = true [target.'cfg(not(target_family = "wasm"))'.dependencies] tokio = { version = "1.24.2", features = ["time"] } -rustls-webpki = "0.102" [target.'cfg(target_family = "wasm")'.dependencies] getrandom = { version = "0.2", features = ["js"], optional = true } @@ -95,6 +95,7 @@ web-sys = { version = "0.3", features = [ [features] default = ["pem"] pem = ["dep:pem"] +ring = ["dep:ring"] ic_ref_tests = [ "default", ] # Used to separate integration tests for ic-ref which need a server running. diff --git a/ic-agent/src/agent/mod.rs b/ic-agent/src/agent/mod.rs index b9fd99f7..e7bf67c2 100644 --- a/ic-agent/src/agent/mod.rs +++ b/ic-agent/src/agent/mod.rs @@ -98,13 +98,9 @@ type AgentFuture<'a, V> = Pin> + ' /// } /// /// # fn create_identity() -> impl ic_agent::Identity { -/// # let rng = ring::rand::SystemRandom::new(); -/// # let key_pair = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng) -/// # .expect("Could not generate a key pair."); /// # -/// # ic_agent::identity::BasicIdentity::from_key_pair( -/// # ring::signature::Ed25519KeyPair::from_pkcs8(key_pair.as_ref()) -/// # .expect("Could not read the key pair."), +/// # ic_agent::identity::BasicIdentity::from_signing_key( +/// # ed25519_consensus::SigningKey::new(rand::thread_rng()) /// # ) /// # } /// # diff --git a/ic-agent/src/identity/basic.rs b/ic-agent/src/identity/basic.rs index d88b9165..58a63c0b 100644 --- a/ic-agent/src/identity/basic.rs +++ b/ic-agent/src/identity/basic.rs @@ -3,7 +3,7 @@ use crate::{agent::EnvelopeContent, export::Principal, Identity, Signature}; #[cfg(feature = "pem")] use crate::identity::error::PemError; -use ring::signature::{Ed25519KeyPair, KeyPair}; +use ed25519_consensus::SigningKey; use simple_asn1::{ oid, to_der, ASN1Block::{BitString, ObjectIdentifier, Sequence}, @@ -13,9 +13,11 @@ use std::fmt; use super::Delegation; -/// A Basic Identity which sign using an ED25519 key pair. +/// A cryptographic identity which signs using an Ed25519 key pair. +/// +/// The caller will be represented via [`Principal::self_authenticating`], which contains the SHA-224 hash of the public key. pub struct BasicIdentity { - key_pair: Ed25519KeyPair, + private_key: KeyCompat, der_encoded_public_key: Vec, } @@ -28,35 +30,65 @@ impl fmt::Debug for BasicIdentity { } impl BasicIdentity { - /// Create a BasicIdentity from reading a PEM file at the path. + /// Create a `BasicIdentity` from reading a PEM file at the path. #[cfg(feature = "pem")] pub fn from_pem_file>(file_path: P) -> Result { Self::from_pem(std::fs::File::open(file_path)?) } - /// Create a BasicIdentity from reading a PEM File from a Reader. + /// Create a `BasicIdentity` from reading a PEM File from a Reader. #[cfg(feature = "pem")] pub fn from_pem(pem_reader: R) -> Result { + use der::{Decode, PemReader}; + use pkcs8::PrivateKeyInfo; + let bytes: Vec = pem_reader .bytes() .collect::, std::io::Error>>()?; + let pki = PrivateKeyInfo::decode(&mut PemReader::new(&bytes)?)?; + let private_key = SigningKey::try_from(pki.private_key)?; + Ok(BasicIdentity::from_signing_key(private_key)) + } - Ok(BasicIdentity::from_key_pair(Ed25519KeyPair::from_pkcs8( - pem::parse(bytes)?.contents(), - )?)) + /// Create a `BasicIdentity` from a `SigningKey` from `ed25519-consensus`. + pub fn from_signing_key(key: SigningKey) -> Self { + let public_key = key.verification_key(); + let der_encoded_public_key = der_encode_public_key(public_key.as_bytes().to_vec()); + + Self { + private_key: KeyCompat::Standard(key), + der_encoded_public_key, + } } - /// Create a BasicIdentity from a KeyPair from the ring crate. - pub fn from_key_pair(key_pair: Ed25519KeyPair) -> Self { + /// Create a `BasicIdentity` from an `Ed25519KeyPair` from `ring`. + #[cfg(feature = "ring")] + pub fn from_key_pair(key_pair: ring::signature::Ed25519KeyPair) -> Self { + use ring::signature::KeyPair; let der_encoded_public_key = der_encode_public_key(key_pair.public_key().as_ref().to_vec()); - Self { - key_pair, + private_key: KeyCompat::Ring(key_pair), der_encoded_public_key, } } } +enum KeyCompat { + Standard(SigningKey), + #[cfg(feature = "ring")] + Ring(ring::signature::Ed25519KeyPair), +} + +impl KeyCompat { + fn sign(&self, payload: &[u8]) -> Vec { + match self { + Self::Standard(k) => k.sign(payload).to_bytes().to_vec(), + #[cfg(feature = "ring")] + Self::Ring(k) => k.sign(payload).as_ref().to_vec(), + } + } +} + impl Identity for BasicIdentity { fn sender(&self) -> Result { Ok(Principal::self_authenticating(&self.der_encoded_public_key)) @@ -75,9 +107,9 @@ impl Identity for BasicIdentity { } fn sign_arbitrary(&self, content: &[u8]) -> Result { - let signature = self.key_pair.sign(content); + let signature = self.private_key.sign(content); Ok(Signature { - signature: Some(signature.as_ref().to_vec()), + signature: Some(signature), public_key: self.public_key(), delegations: None, }) diff --git a/ic-agent/src/identity/delegated.rs b/ic-agent/src/identity/delegated.rs index 0ea7638e..ed482b89 100644 --- a/ic-agent/src/identity/delegated.rs +++ b/ic-agent/src/identity/delegated.rs @@ -1,12 +1,10 @@ use candid::Principal; +use der::{Decode, SliceReader}; use ecdsa::signature::Verifier; use k256::Secp256k1; use p256::NistP256; use pkcs8::{spki::SubjectPublicKeyInfoRef, AssociatedOid, ObjectIdentifier}; -use sec1::{ - der::{Decode, SliceReader}, - EcParameters, EncodedPoint, -}; +use sec1::{EcParameters, EncodedPoint}; use crate::{agent::EnvelopeContent, Signature}; diff --git a/ic-agent/src/identity/error.rs b/ic-agent/src/identity/error.rs index cd14c895..0b540412 100644 --- a/ic-agent/src/identity/error.rs +++ b/ic-agent/src/identity/error.rs @@ -18,9 +18,14 @@ pub enum PemError { #[error("An error occurred while reading the file: {0}")] PemError(#[from] pem::PemError), - /// The key was rejected by Ring. - #[error("A key was rejected by Ring: {0}")] - KeyRejected(#[from] ring::error::KeyRejected), + /// An error occurred while reading the file in DER format. + #[cfg(feature = "pem")] + #[error("An error occurred while reading the file: {0}")] + DerError(#[from] der::Error), + + /// The key was rejected by ed25519-consensus. + #[error("A key was rejected by ed25519-consensus: {0}")] + KeyRejected(#[from] ed25519_consensus::Error), /// The key was rejected by k256. #[error("A key was rejected by k256: {0}")] diff --git a/ic-agent/src/lib.rs b/ic-agent/src/lib.rs index a333016b..882f5e70 100644 --- a/ic-agent/src/lib.rs +++ b/ic-agent/src/lib.rs @@ -43,13 +43,8 @@ //! } //! //! # fn create_identity() -> impl ic_agent::Identity { -//! # let rng = ring::rand::SystemRandom::new(); -//! # let key_pair = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng) -//! # .expect("Could not generate a key pair."); -//! # -//! # ic_agent::identity::BasicIdentity::from_key_pair( -//! # ring::signature::Ed25519KeyPair::from_pkcs8(key_pair.as_ref()) -//! # .expect("Could not read the key pair."), +//! # ic_agent::identity::BasicIdentity::from_signing_key( +//! # ed25519_consensus::SigningKey::new(rand::thread_rng()), //! # ) //! # } //! # diff --git a/ic-transport-types/src/lib.rs b/ic-transport-types/src/lib.rs index 881897d9..206bec35 100644 --- a/ic-transport-types/src/lib.rs +++ b/ic-transport-types/src/lib.rs @@ -17,7 +17,7 @@ mod request_id; pub mod signed; /// The authentication envelope, containing the contents and their signature. This struct can be passed to `Agent`'s -/// `*_signed` methods via [`to_bytes`](Envelope::to_bytes). +/// `*_signed` methods via [`encode_bytes`](Envelope::encode_bytes). #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub struct Envelope<'a> { diff --git a/ic-utils/Cargo.toml b/ic-utils/Cargo.toml index dd0b1774..4ae5f8f5 100644 --- a/ic-utils/Cargo.toml +++ b/ic-utils/Cargo.toml @@ -14,8 +14,6 @@ categories = ["api-bindings", "data-structures", "no-std"] keywords = ["internet-computer", "agent", "utility", "icp", "dfinity"] include = ["src", "Cargo.toml", "../LICENSE", "README.md"] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] async-trait = "0.1.68" candid = { workspace = true, features = ["value"] } @@ -33,8 +31,9 @@ semver = "1.0.7" once_cell = "1.10.0" [dev-dependencies] +ed25519-consensus = { workspace = true } ic-agent = { workspace = true, default-features = true } -ring = { workspace = true } +rand = { workspace = true } tokio = { workspace = true, features = ["full"] } [features] diff --git a/ic-utils/src/call.rs b/ic-utils/src/call.rs index 6889bee3..79d7ea44 100644 --- a/ic-utils/src/call.rs +++ b/ic-utils/src/call.rs @@ -33,7 +33,7 @@ pub trait SyncCall: CallIntoFuture> { } /// A type that implements asynchronous calls (ie. 'update' calls). -/// This can call synchronous and return a [RequestId], or it can wait for the result +/// This can call synchronous and return a [`RequestId`](ic_agent::RequestId), or it can wait for the result /// by polling the agent, and return a type. /// /// The return type must be a tuple type that represents all the values the return @@ -43,15 +43,15 @@ pub trait SyncCall: CallIntoFuture> { pub trait AsyncCall: CallIntoFuture> { /// The return type of the Candid function being called. type Value: for<'de> ArgumentDecoder<'de> + Send; - /// Execute the call, but returns the RequestId. Waiting on the request Id must be + /// Execute the call, but returns the `RequestId`. Waiting on the request Id must be /// managed by the caller using the Agent directly. /// /// Since the return type is encoded in the trait itself, this can lead to types /// that are not compatible to `Out` when getting the result from the Request Id. /// For example, you might hold a [`AsyncCall`], use `call()` and poll for - /// the result, and try to deserialize it as a [String]. This would be caught by - /// Rust type system, but in this case it will be checked at runtime (as Request - /// Id does not have a type associated with it). + /// the result, and try to deserialize it as a [`String`]. This would be caught by + /// Rust type system, but in this case it will be checked at runtime (as `RequestId` + /// does not have a type associated with it). async fn call(self) -> Result, AgentError>; /// Execute the call, and wait for an answer using an exponential-backoff strategy. The return @@ -72,13 +72,8 @@ pub trait AsyncCall: CallIntoFuture> { /// async fn create_a_canister() -> Result> { /// # let canister_wasm = b"\0asm\x01\0\0\0"; /// # fn create_identity() -> impl Identity { - /// # let rng = ring::rand::SystemRandom::new(); - /// # let key_pair = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng) - /// # .expect("Could not generate a key pair."); - /// # - /// # BasicIdentity::from_key_pair( - /// # ring::signature::Ed25519KeyPair::from_pkcs8(key_pair.as_ref()) - /// # .expect("Could not read the key pair."), + /// # BasicIdentity::from_signing_key( + /// # ed25519_consensus::SigningKey::new(rand::thread_rng()), /// # ) /// # } /// # diff --git a/ic-utils/src/canister.rs b/ic-utils/src/canister.rs index b9c5041c..50f88100 100644 --- a/ic-utils/src/canister.rs +++ b/ic-utils/src/canister.rs @@ -389,7 +389,9 @@ mod tests { use super::super::interfaces::ManagementCanister; use crate::call::AsyncCall; use candid::Principal; + use ed25519_consensus::SigningKey; use ic_agent::identity::BasicIdentity; + use rand::thread_rng; fn get_effective_canister_id() -> Principal { Principal::from_text("rwlgt-iiaaa-aaaaa-aaaaa-cai").unwrap() @@ -400,14 +402,7 @@ mod tests { async fn simple() { use super::Canister; - let rng = ring::rand::SystemRandom::new(); - let key_pair = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng) - .expect("Could not generate a key pair."); - - let identity = BasicIdentity::from_key_pair( - ring::signature::Ed25519KeyPair::from_pkcs8(key_pair.as_ref()) - .expect("Could not read the key pair."), - ); + let identity = BasicIdentity::from_signing_key(SigningKey::new(thread_rng())); let port = std::env::var("IC_REF_PORT").unwrap_or_else(|_| "4943".into()); diff --git a/ic-utils/src/interfaces/management_canister.rs b/ic-utils/src/interfaces/management_canister.rs index 7d833c69..485880a0 100644 --- a/ic-utils/src/interfaces/management_canister.rs +++ b/ic-utils/src/interfaces/management_canister.rs @@ -51,7 +51,7 @@ pub enum MgmtMethod { DepositCycles, /// See [`ManagementCanister::raw_rand`]. RawRand, - /// See [`ManagementCanister::provisional_create_canister_with_cycles`]. + /// See [`CreateCanisterBuilder::as_provisional_create_with_amount`]. ProvisionalCreateCanisterWithCycles, /// See [`ManagementCanister::provisional_top_up_canister`]. ProvisionalTopUpCanister, diff --git a/icx/Cargo.toml b/icx/Cargo.toml index 61eb7f6d..db8f197f 100644 --- a/icx/Cargo.toml +++ b/icx/Cargo.toml @@ -23,11 +23,12 @@ anyhow = { version = "1.0", features = ["backtrace"] } candid = { workspace = true, features = ["value"] } candid_parser = { workspace = true } clap = { workspace = true, features = ["derive", "cargo", "color"] } +ed25519-consensus = { workspace = true } hex = { workspace = true } humantime = "2.0.1" ic-agent = { workspace = true, default-features = true } ic-utils = { workspace = true } -ring = { workspace = true } +rand = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true, features = ["full"] } diff --git a/icx/src/main.rs b/icx/src/main.rs index 1b74c074..450ba721 100644 --- a/icx/src/main.rs +++ b/icx/src/main.rs @@ -6,6 +6,7 @@ use candid::{ }; use candid_parser::{check_prog, parse_idl_args, parse_idl_value, IDLProg}; use clap::{crate_authors, crate_version, Parser, ValueEnum}; +use ed25519_consensus::SigningKey; use ic_agent::{ agent::{ self, @@ -21,7 +22,7 @@ use ic_utils::interfaces::management_canister::{ builders::{CanisterInstall, CanisterSettings}, MgmtMethod, }; -use ring::signature::Ed25519KeyPair; +use rand::thread_rng; use std::{ collections::VecDeque, convert::TryFrom, io::BufRead, path::PathBuf, str::FromStr, time::Duration, @@ -36,7 +37,7 @@ const DEFAULT_IC_GATEWAY: &str = "https://ic0.app"; propagate_version(true), )] struct Opts { - /// Some input. Because this isn't an Option it's required to be used + /// The URL of the replica. #[clap(default_value = "http://localhost:8000/")] replica: String, @@ -347,15 +348,7 @@ fn create_identity(maybe_pem: Option) -> impl Identity { if let Some(pem_path) = maybe_pem { BasicIdentity::from_pem_file(pem_path).expect("Could not read the key pair.") } else { - let rng = ring::rand::SystemRandom::new(); - let pkcs8_bytes = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng) - .expect("Could not generate a key pair.") - .as_ref() - .to_vec(); - - BasicIdentity::from_key_pair( - Ed25519KeyPair::from_pkcs8(&pkcs8_bytes).expect("Could not generate the key pair."), - ) + BasicIdentity::from_signing_key(SigningKey::new(thread_rng())) } } diff --git a/ref-tests/Cargo.toml b/ref-tests/Cargo.toml index e2c6397e..6a568013 100644 --- a/ref-tests/Cargo.toml +++ b/ref-tests/Cargo.toml @@ -8,12 +8,13 @@ publish = false [dependencies] candid = { workspace = true } +ed25519-consensus = { workspace = true } ic-agent = { path = "../ic-agent" } ic-identity-hsm = { path = "../ic-identity-hsm" } ic-utils = { path = "../ic-utils", features = ["raw"] } k256 = { workspace = true } p256 = { workspace = true } -ring = { workspace = true } +rand = { workspace = true } serde = { workspace = true, features = ["derive"] } sha2 = { workspace = true } tokio = { workspace = true, features = ["full"] } diff --git a/ref-tests/src/utils.rs b/ref-tests/src/utils.rs index d6938dfc..186e7c29 100644 --- a/ref-tests/src/utils.rs +++ b/ref-tests/src/utils.rs @@ -1,8 +1,9 @@ +use ed25519_consensus::SigningKey; use ic_agent::identity::{Prime256v1Identity, Secp256k1Identity}; use ic_agent::{export::Principal, identity::BasicIdentity, Agent, Identity}; use ic_identity_hsm::HardwareIdentity; use ic_utils::interfaces::{management_canister::builders::MemoryAllocation, ManagementCanister}; -use ring::signature::Ed25519KeyPair; +use rand::thread_rng; use std::{convert::TryFrom, error::Error, future::Future, path::Path}; const HSM_PKCS11_LIBRARY_PATH: &str = "HSM_PKCS11_LIBRARY_PATH"; @@ -49,13 +50,9 @@ fn get_hsm_pin() -> Result { // // A shared container of Ctx objects might be possible instead, but my rust-fu is inadequate. pub fn create_basic_identity() -> Result { - let rng = ring::rand::SystemRandom::new(); - let key_pair = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng) - .expect("Could not generate a key pair."); + let sk = SigningKey::new(thread_rng()); - Ok(BasicIdentity::from_key_pair( - Ed25519KeyPair::from_pkcs8(key_pair.as_ref()).expect("Could not read the key pair."), - )) + Ok(BasicIdentity::from_signing_key(sk)) } /// Create a secp256k1identity, which unfortunately will always be the same one diff --git a/ref-tests/tests/integration.rs b/ref-tests/tests/integration.rs index 19362cf8..9ce5b53f 100644 --- a/ref-tests/tests/integration.rs +++ b/ref-tests/tests/integration.rs @@ -673,6 +673,7 @@ mod sign_send { mod identity { use candid::Principal; + use ed25519_consensus::SigningKey; use ic_agent::{ identity::{ BasicIdentity, DelegatedIdentity, Delegation, Prime256v1Identity, Secp256k1Identity, @@ -680,23 +681,15 @@ mod identity { }, Identity, }; + use rand::thread_rng; use ref_tests::{universal_canister::payload, with_universal_canister_as}; - use ring::{ - rand::{SecureRandom, SystemRandom}, - signature::Ed25519KeyPair, - }; #[ignore] #[test] fn delegated_eddsa_identity() { - let random = SystemRandom::new(); - let mut seed = [0; 32]; - random.fill(&mut seed).unwrap(); - let sending_identity = - BasicIdentity::from_key_pair(Ed25519KeyPair::from_seed_unchecked(&seed).unwrap()); - random.fill(&mut seed).unwrap(); - let signing_identity = - BasicIdentity::from_key_pair(Ed25519KeyPair::from_seed_unchecked(&seed).unwrap()); + let mut random = thread_rng(); + let sending_identity = BasicIdentity::from_signing_key(SigningKey::new(&mut random)); + let signing_identity = BasicIdentity::from_signing_key(SigningKey::new(&mut random)); let delegation = Delegation { expiration: i64::MAX as u64, pubkey: signing_identity.public_key().unwrap(), @@ -729,15 +722,11 @@ mod identity { #[ignore] #[test] fn delegated_ecdsa_identity() { - let random = SystemRandom::new(); - let mut seed = [0; 32]; - random.fill(&mut seed).unwrap(); + let mut random = thread_rng(); let sending_identity = - Secp256k1Identity::from_private_key(k256::SecretKey::from_bytes(&seed.into()).unwrap()); - random.fill(&mut seed).unwrap(); - let signing_identity = Prime256v1Identity::from_private_key( - p256::SecretKey::from_bytes(&seed.into()).unwrap(), - ); + Secp256k1Identity::from_private_key(k256::SecretKey::random(&mut random)); + let signing_identity = + Prime256v1Identity::from_private_key(p256::SecretKey::random(&mut random)); let delegation = Delegation { expiration: i64::MAX as u64, pubkey: signing_identity.public_key().unwrap(),