diff --git a/crates/oxidetalis/src/middlewares/signature.rs b/crates/oxidetalis/src/middlewares/signature.rs index b191d64..f108f4a 100644 --- a/crates/oxidetalis/src/middlewares/signature.rs +++ b/crates/oxidetalis/src/middlewares/signature.rs @@ -71,11 +71,10 @@ pub async fn signature_check( }; if !utils::is_valid_nonce(&signature, &depot.nonce_cache()).await - || !utils::is_valid_signature( - &sender_public_key, - &depot.config().server.private_key, - &signature, + || !depot.config().server.private_key.verify( data.as_bytes(), + &signature, + &sender_public_key, ) { write_err("Invalid signature", UNAUTHORIZED); diff --git a/crates/oxidetalis/src/utils.rs b/crates/oxidetalis/src/utils.rs index 1f4ef34..2bd316b 100644 --- a/crates/oxidetalis/src/utils.rs +++ b/crates/oxidetalis/src/utils.rs @@ -22,8 +22,7 @@ use chrono::Utc; use logcall::logcall; use oxidetalis_config::Postgres; use oxidetalis_core::{ - cipher::K256Secret, - types::{PrivateKey, PublicKey, Signature}, + types::{PublicKey, Signature}, PUBLIC_KEY_HEADER, SIGNATURE_HEADER, }; @@ -50,16 +49,6 @@ pub(crate) async fn is_valid_nonce(signature: &Signature, nonce_cache: &NonceCac new_timestamp && unused_nonce } -/// Returns true if the given signature is valid. -pub(crate) fn is_valid_signature( - signer: &PublicKey, - private_key: &PrivateKey, - signature: &Signature, - data: &[u8], -) -> bool { - K256Secret::from_privkey(private_key).verify(data, signature, signer) -} - /// Extract the sender public key from the request /// /// Returns the public key of the sender extracted from the request, or the diff --git a/crates/oxidetalis/src/websocket/mod.rs b/crates/oxidetalis/src/websocket/mod.rs index dcbdd56..5986203 100644 --- a/crates/oxidetalis/src/websocket/mod.rs +++ b/crates/oxidetalis/src/websocket/mod.rs @@ -23,7 +23,7 @@ use chrono::Utc; use errors::{WsError, WsResult}; use futures::{channel::mpsc, FutureExt, StreamExt, TryStreamExt}; use once_cell::sync::Lazy; -use oxidetalis_core::{cipher::K256Secret, types::PublicKey}; +use oxidetalis_core::types::PublicKey; use oxidetalis_entities::prelude::*; use salvo::{ handler, @@ -102,9 +102,7 @@ pub async fn user_connected( let db_conn = depot.db_conn(); let public_key = utils::extract_public_key(req).expect("The public key was checked in the middleware"); - // FIXME: The config should hold `K256Secret` not `PrivateKey` - let shared_secret = - K256Secret::from_privkey(&depot.config().server.private_key).shared_secret(&public_key); + let shared_secret = depot.config().server.private_key.shared_secret(&public_key); WebSocketUpgrade::new() .upgrade(req, res, move |ws| { diff --git a/crates/oxidetalis_config/src/defaults.rs b/crates/oxidetalis_config/src/defaults.rs index 7ff91e6..f95ab8d 100644 --- a/crates/oxidetalis_config/src/defaults.rs +++ b/crates/oxidetalis_config/src/defaults.rs @@ -25,10 +25,7 @@ pub(crate) mod server { use std::net::{IpAddr, Ipv4Addr}; - use oxidetalis_core::{ - cipher::K256Secret, - types::{PrivateKey, Size}, - }; + use oxidetalis_core::{cipher::K256Secret, types::Size}; pub fn name() -> String { "example.com".to_owned() @@ -39,8 +36,8 @@ pub(crate) mod server { pub const fn port() -> u16 { 7294 } - pub fn private_key() -> PrivateKey { - K256Secret::new().privkey() + pub fn private_key() -> K256Secret { + K256Secret::new() } pub const fn nonce_cache_size() -> Size { Size::MB(1) diff --git a/crates/oxidetalis_config/src/lib.rs b/crates/oxidetalis_config/src/lib.rs index 6388d57..8b1fbd5 100644 --- a/crates/oxidetalis_config/src/lib.rs +++ b/crates/oxidetalis_config/src/lib.rs @@ -23,7 +23,7 @@ use std::{fs, io::Error as IoError, net::IpAddr, path::Path}; use derivative::Derivative; -use oxidetalis_core::types::{PrivateKey, Size}; +use oxidetalis_core::{cipher::K256Secret, types::Size}; use serde::{Deserialize, Serialize}; use toml::{de::Error as TomlDeError, ser::Error as TomlSerError}; @@ -66,7 +66,7 @@ pub struct Server { pub port: u16, /// Server keypair #[derivative(Default(value = "defaults::server::private_key()"))] - pub private_key: PrivateKey, + pub private_key: K256Secret, /// Nonce cache limit #[derivative(Default(value = "defaults::server::nonce_cache_size()"))] pub nonce_cache_size: Size, diff --git a/crates/oxidetalis_core/src/cipher.rs b/crates/oxidetalis_core/src/cipher.rs index 1ccbdf5..9518ab4 100644 --- a/crates/oxidetalis_core/src/cipher.rs +++ b/crates/oxidetalis_core/src/cipher.rs @@ -72,6 +72,7 @@ type HmacSha256 = hmac::Hmac; /// An wrapper around the k256 crate to provide a simple API for ecdh key /// exchange and keypair generation. +#[derive(Clone)] pub struct K256Secret { /// The private key scalar scalar: NonZeroScalar, diff --git a/crates/oxidetalis_core/src/types/impl_serde.rs b/crates/oxidetalis_core/src/types/impl_serde.rs index ee091e0..8a17ebd 100644 --- a/crates/oxidetalis_core/src/types/impl_serde.rs +++ b/crates/oxidetalis_core/src/types/impl_serde.rs @@ -25,6 +25,7 @@ use base58::FromBase58; use serde::{de::Error as DeError, Deserialize, Serialize}; use super::{PrivateKey, PublicKey, Signature}; +use crate::cipher::K256Secret; impl<'de> Deserialize<'de> for PrivateKey { fn deserialize(deserializer: D) -> Result @@ -99,3 +100,21 @@ impl Serialize for Signature { serializer.serialize_str(self.to_string().as_str()) } } + +impl Serialize for K256Secret { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + PrivateKey::serialize(&self.privkey(), serializer) + } +} + +impl<'de> Deserialize<'de> for K256Secret { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Ok(Self::from_privkey(&PrivateKey::deserialize(deserializer)?)) + } +}