From 55056b721cfeb10a054f97bec44ea7b96bb40817 Mon Sep 17 00:00:00 2001 From: Egor Duda Date: Mon, 16 May 2022 21:48:43 +0300 Subject: [PATCH] Use ed25519-compact crate instead of ed25519-dalek ed25519-dalek does not implement Clone and Eq for secret keys, and relevant PR in its repository wait for merge from long time ago, leading to potential problems with maintainability --- Cargo.toml | 4 +-- src/ctap/crypto_wrapper.rs | 53 ++++++++++---------------------------- src/ctap/data_formats.rs | 6 ++--- 3 files changed, 18 insertions(+), 45 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7987184..b33cc1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ serde_json = { version = "=1.0.69", default-features = false, features = ["alloc embedded-time = "0.12.1" arbitrary = { version = "0.4.7", features = ["derive"], optional = true } rand = { version = "0.8.4", optional = true } -ed25519-dalek = { version = "1", default-features = false, features = ["u32_backend", "rand"], optional = true } +ed25519-compact = { version = "1", default-features = false, optional = true } [features] debug_allocations = ["lang_items/debug_allocations"] @@ -37,7 +37,7 @@ with_ctap1 = ["crypto/with_ctap1"] with_nfc = ["libtock_drivers/with_nfc"] vendor_hid = ["libtock_drivers/vendor_hid"] fuzz = ["arbitrary", "std"] -ed25519 = ["ed25519-dalek"] +ed25519 = ["ed25519-compact"] [dev-dependencies] enum-iterator = "0.6.0" diff --git a/src/ctap/crypto_wrapper.rs b/src/ctap/crypto_wrapper.rs index 8abe29f..73da5eb 100644 --- a/src/ctap/crypto_wrapper.rs +++ b/src/ctap/crypto_wrapper.rs @@ -14,8 +14,10 @@ use crate::ctap::data_formats::{ extract_array, extract_byte_string, CoseKey, PublicKeyCredentialSource, - PublicKeyCredentialType, SignatureAlgorithm, ES256_ALGORITHM, EDDSA_ALGORITHM, + PublicKeyCredentialType, SignatureAlgorithm, ES256_ALGORITHM, }; +#[cfg(feature="ed25519")] +use crate::ctap::data_formats::EDDSA_ALGORITHM; use crate::ctap::status_code::Ctap2StatusCode; use crate::ctap::storage; use crate::env::Env; @@ -30,8 +32,6 @@ use crypto::sha256::Sha256; use rng256::Rng256; use sk_cbor as cbor; use sk_cbor::{cbor_array, cbor_bytes, cbor_int}; -#[cfg(feature = "ed25519")] -use ed25519_dalek::Signer; // Legacy credential IDs consist of // - 16 bytes: initialization vector for AES-256, @@ -101,37 +101,13 @@ pub fn aes256_cbc_decrypt( } /// An asymmetric private key that can sign messages. -#[derive(Debug)] +#[derive(Clone,Debug,PartialEq,Eq)] pub enum PrivateKey { Ecdsa(ecdsa::SecKey), #[cfg(feature = "ed25519")] - Ed25519(ed25519_dalek::Keypair), + Ed25519(ed25519_compact::SecretKey), } -impl Clone for PrivateKey { - fn clone(&self) -> Self { - match self { - Self::Ecdsa(sk) => Self::Ecdsa (sk.clone ()), - #[cfg(feature = "ed25519")] - Self::Ed25519(keypair) => Self::Ed25519 (ed25519_dalek::Keypair::from_bytes (&keypair.to_bytes()).unwrap()), - } - } -} - -impl PartialEq for PrivateKey { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (&Self::Ecdsa(ref a), &Self::Ecdsa(ref b)) => a == b, - #[cfg(feature = "ed25519")] - (&Self::Ed25519(ref a), &Self::Ed25519(ref b)) => a.to_bytes() == b.to_bytes(), - #[cfg(feature = "ed25519")] - _ => false, - } - } -} - -impl Eq for PrivateKey {} - impl PrivateKey { /// Creates a new private key for the given algorithm. /// @@ -165,12 +141,8 @@ impl PrivateKey { if bytes.len() != 32 { return None; } - if let Ok(secret) = ed25519_dalek::SecretKey::from_bytes(bytes) { - let public = ed25519_dalek::PublicKey::from (&secret); - Some(Self::Ed25519(ed25519_dalek::Keypair{secret, public})) - } else { - None - } + let seed = ed25519_compact::Seed::from_slice(bytes).unwrap(); + Some(Self::Ed25519(ed25519_compact::KeyPair::from_seed(seed).sk)) } /// Returns the corresponding public key. @@ -178,7 +150,7 @@ impl PrivateKey { match self { PrivateKey::Ecdsa(ecdsa_key) => CoseKey::from(ecdsa_key.genpk()), #[cfg(feature = "ed25519")] - PrivateKey::Ed25519(ed25519_keypair) => CoseKey::from(ed25519_keypair.public), + PrivateKey::Ed25519(ed25519_key) => CoseKey::from(ed25519_key.public_key()), } } @@ -187,7 +159,7 @@ impl PrivateKey { match self { PrivateKey::Ecdsa(ecdsa_key) => ecdsa_key.sign_rfc6979::(message).to_asn1_der(), #[cfg(feature = "ed25519")] - PrivateKey::Ed25519(ed25519_keypair) => ed25519_keypair.try_sign(message).unwrap().to_bytes().to_vec(), + PrivateKey::Ed25519(ed25519_key) => ed25519_key.sign(message,None).to_vec(), } } @@ -209,7 +181,7 @@ impl PrivateKey { key_bytes } #[cfg(feature = "ed25519")] - PrivateKey::Ed25519(ed25519_keypair) => ed25519_keypair.secret.to_bytes().to_vec(), + PrivateKey::Ed25519(ed25519_key) => ed25519_key.seed().to_vec(), } } } @@ -285,8 +257,9 @@ pub fn encrypt_key_handle( ECDSA_CREDENTIAL_ID_VERSION } #[cfg(feature = "ed25519")] - PrivateKey::Ed25519(keypair) => { - plaintext[0..32].copy_from_slice(&keypair.secret.to_bytes()); + PrivateKey::Ed25519(ed25519_key) => { + let sk_bytes = *ed25519_key.seed(); + plaintext[0..32].copy_from_slice(&sk_bytes); ED25519_CREDENTIAL_ID_VERSION } }; diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index 337e5af..30b73d9 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -844,10 +844,10 @@ impl From for CoseKey { } #[cfg(feature = "ed25519")] -impl From for CoseKey { - fn from(pk: ed25519_dalek::PublicKey) -> Self { +impl From for CoseKey { + fn from(pk: ed25519_compact::PublicKey) -> Self { CoseKey { - x_bytes: pk.to_bytes(), + x_bytes: *pk, y_bytes: [0u8; 32], key_type: CoseKey::OKP_KEY_TYPE, curve: CoseKey::ED25519_CURVE,