From 802cc80799c294113fc4104808c210e94e49587a Mon Sep 17 00:00:00 2001 From: cooki Date: Mon, 25 Nov 2024 21:37:42 +0000 Subject: [PATCH] update --- Cargo.toml | 2 +- src/bucket/bucket_guid.rs | 4 +- src/bucket/bucket_path.rs | 1 - src/bucket/encryption.rs | 1 - src/bucket_search_query.rs | 9 +- src/key/derived_key.rs | 3 +- src/key/master_key.rs | 68 +++++----- src/key/master_key_builder.rs | 94 ++++++++------ src/key/memory/secure_generic_array.rs | 29 +++-- src/key/mod.rs | 6 - src/key/nonce_generator.rs | 18 ++- src/lib.rs | 13 +- .../centralized/centralized_share_link.rs | 10 +- .../decentralized_share_link_url_encoded.rs | 118 ++++++++++-------- .../decentralized_share_token.rs | 11 +- .../decentralized_share_token_signature.rs | 7 +- src/share/share_link_token.rs | 6 +- src/share/token_path.rs | 4 +- src/token/bearer_token.rs | 6 +- src/unix_timestamp.rs | 4 +- 20 files changed, 214 insertions(+), 200 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a298493..cf0f446 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ pbkdf2 = "0.12.2" generic-array = { version = "1.1.1", optional = true, features = ["zeroize"] } argon2 = {version = "*", optional = true } zeroize = {version = "1.8.1", features = ["derive", "simd"] } -secrecy = { version = "0.10.3", optional = true } +secrecy = { version = "0.10.3", optional = true } vsss-rs = {version = "4.3.8", optioanl = true } pkcs8 = { version = "0.10.2" , opotional = true} chacha20poly1305 = "0.10.1" diff --git a/src/bucket/bucket_guid.rs b/src/bucket/bucket_guid.rs index 2a821bf..04fe58b 100644 --- a/src/bucket/bucket_guid.rs +++ b/src/bucket/bucket_guid.rs @@ -1,7 +1,5 @@ -use core::slice::SlicePattern; -use std::{fmt, mem}; +use std::fmt; use std::str::FromStr; -use logos::Source; use serde::{Deserialize, Serialize}; use uuid::Uuid; diff --git a/src/bucket/bucket_path.rs b/src/bucket/bucket_path.rs index 118d19a..9e33176 100644 --- a/src/bucket/bucket_path.rs +++ b/src/bucket/bucket_path.rs @@ -1,6 +1,5 @@ use crate::bucket::bucket_guid::BucketGuid; use std::fmt::Debug; -use std::fmt::Display; use std::str::FromStr; // Path implementation for bucket. diff --git a/src/bucket/encryption.rs b/src/bucket/encryption.rs index 4fcc6d8..a1b2cf1 100644 --- a/src/bucket/encryption.rs +++ b/src/bucket/encryption.rs @@ -11,7 +11,6 @@ use std::fmt; use std::fmt::Display; use std::num::ParseIntError; use std::str::FromStr; -use pkcs8::ObjectIdentifier; use serde::{Deserialize, Serialize}; use strum::{Display, EnumString}; diff --git a/src/bucket_search_query.rs b/src/bucket_search_query.rs index f66adbf..7767202 100644 --- a/src/bucket_search_query.rs +++ b/src/bucket_search_query.rs @@ -99,11 +99,8 @@ pub fn parse_search(search: &str) -> Vec { } Ok(SearchTokenKey::Tag) => { if let Some(token_val) = lexer.next() { - match token_val { - Ok(SearchTokenKey::Word(word)) => { - token_values.push(SearchTokensValue::Tag(word.to_string())); - } - _ => {} + if let Ok(SearchTokenKey::Word(word)) = token_val { + token_values.push(SearchTokensValue::Tag(word.to_string())); } } } @@ -198,7 +195,7 @@ impl FromStr for BucketSearchQuery { let mut query = s.to_string(); let fragments: Vec<&str> = s.split(';').collect(); - if fragments.len() == 0 { + if fragments.is_empty() { return Ok(BucketSearchQuery { query: s.to_string(), flags: Vec::new(), diff --git a/src/key/derived_key.rs b/src/key/derived_key.rs index 96c78a4..f0cb315 100644 --- a/src/key/derived_key.rs +++ b/src/key/derived_key.rs @@ -1,4 +1,3 @@ -use std::{default, ops::DerefMut}; use generic_array::GenericArray; use secrecy::{ExposeSecret, ExposeSecretMut}; @@ -20,7 +19,7 @@ impl DerivedKey { /// Creates a derive key from the master key using KDF function. pub fn new(master_key: &MasterKey256, bucket_guid: &BucketGuid, params: &DeriveKeyParams) -> Self{ let mut secrete = SecreteGenericArray::new(GenericArray::::default()); - pbkdf2::pbkdf2_hmac::(&master_key.key.expose_secret(), &bucket_guid.to_bytes(), params + pbkdf2::pbkdf2_hmac::(master_key.key.expose_secret(), &bucket_guid.to_bytes(), params .rounds , secrete.expose_secret_mut()); Self { diff --git a/src/key/master_key.rs b/src/key/master_key.rs index 0943837..997b950 100644 --- a/src/key/master_key.rs +++ b/src/key/master_key.rs @@ -1,39 +1,45 @@ -use argon2::password_hash::{Salt, SaltString}; -use argon2::{Argon2, PasswordHash, PasswordHasher}; -use rand::CryptoRng; -use core::slice::SlicePattern; +use argon2::password_hash::SaltString; +use argon2::{Argon2, PasswordHasher}; //use hex_literal::hex; -use digest::generic_array::{ArrayLength, GenericArray}; -use secrecy::ExposeSecret; use sha3::{Digest, Sha3_256}; -use std::convert::Infallible; use digest::typenum; -use pkcs8::{ObjectIdentifier, PrivateKeyInfo}; -use pkcs8::spki::AlgorithmIdentifier; +use pkcs8::ObjectIdentifier; use super::memory::secure_generic_array::SecreteGenericArray; pub struct MasterKey256 { pub key: SecreteGenericArray, } +#[derive(thiserror::Error, Debug)] +pub enum MasterKey256Error { + #[error("Failed to encode salt as base64")] + SaltEncodingError, + #[error("Argon2 error")] + PasswordHashError(argon2::password_hash::Error), +} impl MasterKey256 { - - fn new(argon2: &Argon2, password: impl AsRef<[u8]>, salt: SaltString) -> Result + fn new(argon2: &Argon2, password: impl AsRef<[u8]>, salt: SaltString) + -> Result where Self: Sized { - let mut hasher = Self::CryptoHasher::new(); - hasher.update(salt); + let mut hasher = Sha3_256::new(); + hasher.update(salt.as_salt().as_str().as_bytes()); let mac = hasher.finalize(); + + let salt_string = SaltString::encode_b64(&mac) + .map_err(|_| MasterKey256Error::SaltEncodingError)?; let password_hash = argon2 - .hash_password(password.as_ref(), mac.as_slice())?; + .hash_password(password.as_ref(), &salt_string) + .map_err(MasterKey256Error::PasswordHashError)?; + debug_assert_eq!(password_hash.hash.unwrap().as_bytes().len(), 32); - let key = SecreteGenericArray::new(password_hash.hash.unwrap().as_bytes()); - Ok(MasterKey256 { - key, - }) + let key = SecreteGenericArray::new( + generic_array::GenericArray::from_slice(password_hash.hash.unwrap().as_bytes()).to_owned() + ); + Ok(MasterKey256 { key }) } } @@ -42,19 +48,19 @@ pub enum MasterKey256ParseError { } -impl TryInto> for MasterKey256 { - type Error = Infallible; - fn try_into(self) -> Result, Self::Error> { - Ok(PrivateKeyInfo { - algorithm: AlgorithmIdentifier { - oid: (), - parameters: None, - }, - private_key: &self.secrete.0, - public_key: None, - }) - } -} +//impl TryInto> for MasterKey256 { +// type Error = Infallible; +// fn try_into(self) -> Result, Self::Error> { +// Ok(PrivateKeyInfo { +// algorithm: AlgorithmIdentifier { +// oid: (), +// parameters: None, +// }, +// private_key: self.key.0.expose_secret(), +// public_key: None, +// }) +// } +//} impl MasterKey256 { pub fn oid() -> Option { diff --git a/src/key/master_key_builder.rs b/src/key/master_key_builder.rs index 9946416..9a86aef 100644 --- a/src/key/master_key_builder.rs +++ b/src/key/master_key_builder.rs @@ -1,15 +1,11 @@ -use argon2::password_hash::Salt; -use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier}; +use argon2::PasswordHash; use generic_array::GenericArray; -use p256::elliptic_curve::bigint::Encoding; -use p256::elliptic_curve::{Curve, PrimeField}; +use p256::elliptic_curve::bigint::{Encoding, NonZero}; use p256::{NistP256, U256}; -use vsss_rs::elliptic_curve::Scalar; -use vsss_rs::{combine_shares, shamir::split_secret, Gf256}; -use rand::{thread_rng, CryptoRng, RngCore, SeedableRng}; - +use vsss_rs::{combine_shares, shamir::split_secret}; +use rand::{CryptoRng, RngCore, SeedableRng}; use crate::key::memory::secure_generic_array::SecreteGenericArray; - +use p256::Scalar; use super::master_key::MasterKey256; #[derive(Clone, Debug, PartialEq, Eq)] @@ -51,7 +47,7 @@ pub struct MasterKeyBuilder { pub struct SecreteShare { - pub share: Gf256, + pub share: Vec, } pub struct Secretes { @@ -63,7 +59,7 @@ pub struct Secretes { impl MasterKeyBuilder { pub fn new(params: VerifiableSecretSharingSchemeParams) -> Self { if params.validate() { - return Self { + Self { params, } } else { @@ -71,24 +67,29 @@ impl MasterKeyBuilder { } } - pub fn combine(&self, secrete_shares: Vec) -> MasterKey256 { + pub fn combine(&self, secrete_shares: Vec) -> MasterKey256 { assert!( secrete_shares.len() >= self.params.threshold, "Not enough shares to meet the threshold" ); - + // Convert SecreteShare to Vec for reconstruction + let shares: Vec> = secrete_shares.iter() + .map(|s| s.share.clone()) + .collect(); + // Reconstruct the secret - let reconstructed_secret = combine_shares(&secrete_shares.as_slice()).expect("Failed to combine shares"); - + let reconstructed_secret: p256::Scalar = combine_shares::>(&shares) + .expect("Failed to combine shares"); + // Wrap the reconstructed secret into a `MasterKey256` MasterKey256 { - key: SecreteGenericArray::new(reconstructed_secret.to_bytes()), + key:SecreteGenericArray::new(*GenericArray::from_slice(&reconstructed_secret.to_bytes())), } } /// Build and return generated master keys - pub fn build<'a>(&self, kdf: PasswordHash<'a>) -> Secretes { + pub fn build(&self, kdf: PasswordHash<'_>) -> Secretes { let kdf_output = kdf.hash.expect("Password hash is missing"); assert_eq!( kdf_output.len(), @@ -96,34 +97,47 @@ impl MasterKeyBuilder { "Password hash must be 256 bits (32 bytes)" ); - // Convert password hash to scalar - let modulus = NistP256::ORDER; - let mut value = U256::from_be_slice(&kdf_output.as_bytes()); - value = value % modulus; // Reduce modulo p - let secrete_scalar = Scalar::from_repr(value.to_be_bytes().into()) + // Convert password hash to scalar securely + let modulus = ::ORDER; + let mut value = U256::from_be_slice(kdf_output.as_bytes()); + let non_zero_modulus = NonZero::new(modulus).expect("Modulus cannot be zero"); + value = value.rem(&non_zero_modulus); // Reduce modulo p + let secret_scalar = p256::NonZeroScalar::from_repr(value.to_be_bytes().into()) .expect("Failed to create Scalar from password hash"); - - - // Split the secret into shares - let mut deterministic_rng = DeterministicRng::seed_from_u64(102312343859310); - let shares = split_secret(self.params.threshold.clone(), - self.params.limit.clone(), - secrete_scalar, - deterministic_rng) - .expect("Failed to split secret"); - - - - // Wrap shares into `SplitSecret` - let split_keys = shares + // Create a deterministic seed from the KDF output + let seed = { + let mut hasher = blake3::Hasher::new(); + hasher.update(kdf_output.as_bytes()); + hasher.update(b"rng_seed"); // Domain separation + let hash = hasher.finalize(); + let mut seed = [0u8; 16]; + seed.copy_from_slice(&hash.as_bytes()[0..16]); + seed + }; + + let mut deterministic_rng = DeterministicRng::from_seed(seed); + + // Split the secret into shares + //let scalar_bytes = secret_scalar.to_repr().as_ref().to_vec(); + let shares = split_secret::>( + self.params.threshold, + self.params.limit, + *secret_scalar.as_ref(), + &mut deterministic_rng + ).expect("Failed to split secret"); + + // Wrap shares into SecretShare + let secret_shares: Vec = shares .into_iter() - .map(|share| SecreteShare { share: share }) + .map(|share| SecreteShare { share }) .collect(); - let a = generic_array::GenericArray::::from_slice(kdf_output.as_bytes()); + Secretes { - master_key: MasterKey256 { key: SecreteGenericArray::new( *a ) }, - secrete_shares: split_keys, + master_key: MasterKey256 { + key: SecreteGenericArray::new(GenericArray::from_slice(kdf_output.as_bytes() ).to_owned() ) + }, + secrete_shares: secret_shares, threshold: self.params.threshold, } } diff --git a/src/key/memory/secure_generic_array.rs b/src/key/memory/secure_generic_array.rs index 67278d0..35509d2 100644 --- a/src/key/memory/secure_generic_array.rs +++ b/src/key/memory/secure_generic_array.rs @@ -1,4 +1,4 @@ -use std::{alloc::{AllocError, Allocator, Global, Layout}, convert::Infallible, default, ops::{Deref, DerefMut}}; +use std::{alloc::{AllocError, Allocator, Global}, u8}; use generic_array::{ArrayLength, GenericArray}; use rand::{CryptoRng, RngCore}; use secrecy::{ExposeSecret, ExposeSecretMut, SecretBox}; @@ -28,19 +28,19 @@ where { /// Creates a new `SecureGenericArray` with global allocator, no memory specific protection. pub fn new(inner: GenericArray) -> Self { - Self::new_in(inner, &Global).unwrap() + Self::new_in(inner, Global).unwrap() } /// Creates a new `SecureGenericArray` using a custom allocator. pub fn new_in( inner: GenericArray, - allocator:&TAllocator, + allocator:TAllocator, ) -> Result where TAllocator: Allocator + ?CryptoSecureAllocator, // Might be crpyot secure allocator, pls mark it if it's required but also need support for global allocator. { - // Wrap the allocated memory in a `SecretBox`. - let boxed = unsafe { Box::::from_raw_in( inner.as_mut_ptr(), allocator) }; + // Wrap the allocated memory in a `SecretBox`. + let boxed = Box::new_in(inner, Global); // TODO: Add support for the actual allocator, currently secrecy only support global allocator. Switch this out for TAllocator. Ok(Self(SecretBox::new(boxed))) } @@ -52,14 +52,21 @@ where ) -> Result where TCryptoRng: RngCore + CryptoRng, + TAllocator: Allocator, + T: From, // Add this bound to allow conversion from u8 to T T: Default, - TAllocator: Allocator { - let mut slice = GenericArray::::default(); - rng.fill_bytes(&mut slice); - Ok( - Self::new_in(slice, allocator)? - ) + let mut array = GenericArray::::default(); + // Create a temporary buffer for random bytes + let mut bytes = vec![0u8; array.len()]; + rng.fill_bytes(&mut bytes); + + // Convert each byte to type T + for (i, byte) in bytes.iter().enumerate() { + array[i] = T::from(*byte); + } + + Self::new_in(array, allocator) } } diff --git a/src/key/mod.rs b/src/key/mod.rs index 7e72597..bb2903c 100644 --- a/src/key/mod.rs +++ b/src/key/mod.rs @@ -1,11 +1,5 @@ -use argon2::password_hash::SaltString; -use argon2::Argon2; -use core::slice::SlicePattern; -use std::hash::Hash; -use digest::{Digest, FixedOutput}; use generic_array::typenum::IsGreaterOrEqual; use generic_array::{ArrayLength, GenericArray}; -use secrecy::ExposeSecret; use std::fmt::Debug; use zeroize::Zeroize; diff --git a/src/key/nonce_generator.rs b/src/key/nonce_generator.rs index ebe2457..cd8fa82 100644 --- a/src/key/nonce_generator.rs +++ b/src/key/nonce_generator.rs @@ -1,10 +1,9 @@ use generic_array::{typenum::IsGreaterOrEqual, ArrayLength, GenericArray}; -use vsss_rs::elliptic_curve::bigint; use zeroize::Zeroize; use crate::bucket::bucket_guid::BucketGuid; -use super::{DeterministicNonceGenerator, Nonce, NonceGenerator}; +use super::{Nonce, NonceGenerator}; /// 96-bit random sequential generator. /// Generates a random cryptographically secure nonce. @@ -42,9 +41,9 @@ pub struct DeterministicHashSequentialNonceGenerator { impl DeterministicHashSequentialNonceGenerator { pub fn new(val: &BucketGuid) -> Self { - + let bytes = val.to_bytes(); Self { - seed: todo!(), + seed: u128::from_be_bytes(bytes[..16].try_into().unwrap()), } } } @@ -55,6 +54,13 @@ TNonceLength: ArrayLength, TNonceLength: IsGreaterOrEqual { fn next(&mut self) -> Nonce { - + let mut nonce = GenericArray::default(); + // Use first 8 bytes of seed for first part of nonce + nonce[0..8].copy_from_slice(&(self.seed as u64).to_be_bytes()); + // Use second 8 bytes of seed for second part + nonce[8..16].copy_from_slice(&((self.seed >> 64) as u64).to_be_bytes()); + // Increment seed for next nonce + self.seed = self.seed.wrapping_add(1); + Nonce(nonce) } -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 5e3a6fd..39dbc86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,15 +4,8 @@ #![feature(allocator_api)] extern crate core; -use core::slice::SlicePattern; -use serde::de::Expected; -use serde::{Deserialize, Serialize, Serializer}; -use std::fmt::{Debug, LowerExp}; -use std::{ - fmt::Display, - str::FromStr, -}; -use strum::IntoEnumIterator; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; #[cfg(feature = "search_query")] @@ -124,7 +117,7 @@ pub enum DownloadFormat { #[cfg(test)] mod tests { use crate::bucket::bucket_guid::BucketGuid; - use super::*; + #[test] fn test_bucket_guid_display() { diff --git a/src/share/centralized/centralized_share_link.rs b/src/share/centralized/centralized_share_link.rs index d5c28a3..0e7ebc7 100644 --- a/src/share/centralized/centralized_share_link.rs +++ b/src/share/centralized/centralized_share_link.rs @@ -2,13 +2,10 @@ use crate::share::centralized::centralized_share_link_token::CentralizedShareLin use crate::share::fully_qualified_domain_name::FullyQualifiedDomainName; use crate::share::token_path::TokenPath; use crate::share::versioning::SharingApiPath; -use crate::util::{DOMAIN_NAME, DOMAIN_URL}; -use base64::Engine; +use crate::util::DOMAIN_NAME; use http::uri::Scheme; use http::Uri; use std::convert::Infallible; -use std::fmt::Display; -use std::io::BufRead; use std::str::FromStr; /// Would use the URL create to store the data but the URL crate does not have a Builder Pattern only parser, very sad. @@ -29,10 +26,7 @@ impl TryFrom for CentralizedShareLink { token: value.token, }; - let subdomain = match value.region { - None => { None } - Some(region) => { Some( Box::from( region.to_string().as_str())) } - }; + let subdomain = value.region.map(|region| Box::from( region.to_string().as_str())); let fqdn = FullyQualifiedDomainName { subdomain, diff --git a/src/share/decentralized/decentralized_share_link_url_encoded.rs b/src/share/decentralized/decentralized_share_link_url_encoded.rs index 67d3c0c..75da849 100644 --- a/src/share/decentralized/decentralized_share_link_url_encoded.rs +++ b/src/share/decentralized/decentralized_share_link_url_encoded.rs @@ -1,11 +1,6 @@ use std::fmt::{Display, Formatter}; -use aes_gcm; -use base64::{Engine, engine::general_purpose}; -use http::uri::Scheme; -use secrecy::ExposeSecret; -use time::OffsetDateTime; -use crate::bucket::bucket_feature_flags::{self, BucketFeaturesFlags}; +use crate::bucket::bucket_feature_flags::{BucketFeaturesFlags}; use crate::bucket::bucket_guid::BucketGuid; use crate::bucket::bucket_permission::BucketPermissionFlags; use crate::bucket::encryption::BucketEncryptionScheme; @@ -14,28 +9,36 @@ use crate::region::DatacenterRegion; use crate::share::fully_qualified_domain_name::FullyQualifiedDomainName; use crate::share::versioning::SharingApiPath; use crate::util::DOMAIN_NAME; +use base64::{engine::general_purpose, Engine}; +use ed25519_compact::SecretKey; +use http::uri::Scheme; +use secrecy::ExposeSecret; +use sha3::Sha3_256; +use time::OffsetDateTime; -use super::decentralized_share_token::{DecentralizedSecretShareToken, DecentralizedSecreteShareTokenError}; -use super::decentralized_share_token_signature::{DecentralizedShareTokenSignature, DecentralizedShareTokenSignatureError}; - +use super::decentralized_share_token::{ + DecentralizedSecretShareToken, DecentralizedSecretShareTokenError, +}; +use super::decentralized_share_token_signature::{ + DecentralizedShareTokenSignature, DecentralizedShareTokenSignatureError, +}; // https:eu-central-1.1.bucketdrive.co/share/0#user_id#bucket_id#bucket_encryption#bucket_key#permission#expires#signature - // The Only difference between ShareLink and SecretShareLink is // that SecretShareLink encode the key for decrypting the bucket in an url such as Aes256Gcm. // And that SecretShareLink use pub struct DecentralizedSecretShareLink { - pub scheme: Scheme, - pub region_cluster: Option, - pub fqdn: FullyQualifiedDomainName, - pub path: DecentralizedSecretesPath, + pub scheme: Scheme, + pub region_cluster: Option, + pub fqdn: FullyQualifiedDomainName, + pub path: DecentralizedShareParams, // acctual params for the specific bucket, encoded is stored in fragment port of uri as to not leak it to the server. // Token, is not encoded into urls, not needed, signature is enough. - pub token: DecentralizedSecretShareToken, + pub token: DecentralizedSecretShareToken, // token of path } -pub struct DecentralizedSecretesPath { - // Depending on what encryption used, the bucket_key might be different. +pub struct DecentralizedShareParams { + // Depending on what encryption used, the bucket_key might be different. // Note that the encryption algorithm chosen should have built in integrity check such as AES256-GCM to be considered fully secure or need an external source of integrity check. // Only the official supported bucket encryption can be used on the website, // any encryption that fal under custom will only be supported by client @@ -54,29 +57,38 @@ pub struct DecentralizedSecretesPath { pub permission: BucketPermissionFlags, /// For how long the signature is going to be valid pub expires: OffsetDateTime, - /// Signature of the token. - pub token_signature: DecentralizedShareTokenSignature, + /// Signature of the token, will be set by the decentralzied secrete share link so don't worry about it. + pub token_signature: Option, } - -impl Display for DecentralizedSecretesPath { +impl Display for DecentralizedShareParams { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - - write!(f, "{}{}/{}#{}#{}", - self.version, - self.bucket_guid, - general_purpose::URL_SAFE_NO_PAD.encode(&self.expires.to_string()), - general_purpose::URL_SAFE_NO_PAD.encode(&self.permission.bits().to_be_bytes()), - general_purpose::URL_SAFE_NO_PAD.encode(&self.token_signature.0) + write!( + f, + "{}{}/{}#{}", + self.version, + self.bucket_guid, + general_purpose::URL_SAFE_NO_PAD.encode(self.expires.to_string()), + general_purpose::URL_SAFE_NO_PAD.encode(self.permission.bits().to_be_bytes()), )?; + match &self.token_signature { + Some(token_signature) => { + write!( + f, + "#{}", + general_purpose::URL_SAFE_NO_PAD.encode(token_signature.0) + )?; + } + None => {} + } match &self.secrete_key { - Some(secrete_key) => { - write!(f, "#{}", + Some(secrete_key) => write!( + f, + "#{}", general_purpose::URL_SAFE_NO_PAD.encode(secrete_key.key.expose_secret()) - )? - }, - None => {}, + )?, + None => {} } Ok(()) } @@ -85,18 +97,13 @@ impl Display for DecentralizedSecretesPath { impl Display for DecentralizedSecretShareLink { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}://",self.scheme)?; + write!(f, "{}://", self.scheme)?; match &self.region_cluster { - Some(region_cluster) => { write!(f, "{}.", region_cluster)? }, - None => {}, + Some(region_cluster) => write!(f, "{}.", region_cluster)?, + None => {} } - write!( - f, - "{}{}", - self.fqdn, - self.path - ) + write!(f, "{}{}", self.fqdn, self.path) } } @@ -121,7 +128,7 @@ pub enum SecretShareLinkVerifySignatureError { #[derive(thiserror::Error, Debug)] pub enum DecentralizedSecreteShareLinkError { #[error(transparent)] - DecentralizedSecreteShareTokenError(#[from] DecentralizedSecreteShareTokenError), + DecentralizedSecretShareTokenError(#[from] DecentralizedSecretShareTokenError), #[error(transparent)] DecentralizedShareTokenSignatureError(#[from] DecentralizedShareTokenSignatureError), } @@ -130,20 +137,25 @@ impl DecentralizedSecretShareLink { const VERSION: SharingApiPath = SharingApiPath::V1; pub fn new( region_cluster: Option, - path: DecentralizedSecretesPath, + mut path: DecentralizedShareParams, bucket_feature_flags: &BucketFeaturesFlags, + secrete_signing_key: &SecretKey, ) -> Result { - - let token = DecentralizedSecretShareToken::new::(®ion_cluster, &path.bucket_guid, &path.secrete_key, &path.permission, &path.expires, &bucket_feature_flags)?; - let token_signature = DecentralizedShareTokenSignature::new(&token, &path.secrete_key, &path.bucket_guid)?; - - let subdomain = match region_cluster { - Some(region_cluster) => Some(region_cluster.to_string().into_boxed_str()), - None => None, - }; + let token = DecentralizedSecretShareToken::new::( + ®ion_cluster, + &path.bucket_guid, + &path.secrete_key, + &path.permission, + &path.expires, + bucket_feature_flags, + )?; + let token_signature = + DecentralizedShareTokenSignature::new(&token, secrete_signing_key, &path.bucket_guid)?; + path.token_signature = Some(token_signature); + let subdomain = region_cluster.as_ref().map(|region_cluster| region_cluster.to_string().into_boxed_str()); let fqdn = FullyQualifiedDomainName { - subdomain: subdomain, + subdomain, domain: Box::from(DOMAIN_NAME), top_level_domain: Box::from(".co"), }; diff --git a/src/share/decentralized/decentralized_share_token.rs b/src/share/decentralized/decentralized_share_token.rs index a654e17..d4e8b04 100644 --- a/src/share/decentralized/decentralized_share_token.rs +++ b/src/share/decentralized/decentralized_share_token.rs @@ -34,7 +34,7 @@ impl DecentralizedSecretShareToken { pub fn hash( region_cluster: &Option, bucket_guid: &BucketGuid, - secret_key: &DerivedKey, + secret_key: &Option, permission: &BucketPermissionFlags, expires: &OffsetDateTime, ) -> Result, bincode::Error> @@ -44,7 +44,12 @@ impl DecentralizedSecretShareToken { hasher.update(region.to_string()); } hasher.update(bucket_guid.to_bytes()); - hasher.update(secret_key.key.expose_secret()); + match secret_key { + Some(secret_key) => { + hasher.update(secret_key.key.expose_secret()); + }, + None => { }, + }; hasher.update(permission.bits().to_be_bytes()); hasher.update(bincode::serialize(expires)?); Ok(hasher.finalize()) @@ -54,7 +59,7 @@ impl DecentralizedSecretShareToken { pub fn new( region_cluster: &Option, bucket_guid: &BucketGuid, - secret_key: &DerivedKey, + secret_key: &Option, permission: &BucketPermissionFlags, expires: &OffsetDateTime, bucket_features_flags: &BucketFeaturesFlags, diff --git a/src/share/decentralized/decentralized_share_token_signature.rs b/src/share/decentralized/decentralized_share_token_signature.rs index 9940418..fdd8232 100644 --- a/src/share/decentralized/decentralized_share_token_signature.rs +++ b/src/share/decentralized/decentralized_share_token_signature.rs @@ -1,5 +1,4 @@ use core::slice::SlicePattern; -use std::convert::Infallible; use ed25519_compact::{Noise, PublicKey, SecretKey, Signature}; @@ -31,9 +30,7 @@ impl DecentralizedShareTokenSignature { let siganture = secret_key.sign(token.as_slice(), Some(noise)); Ok( - Self { - 0: siganture - } + Self(siganture) ) } @@ -48,6 +45,6 @@ impl DecentralizedShareTokenSignature { public_key: &PublicKey, token: &ShareLinkToken, ) -> Result<(), ed25519_compact::Error> { - public_key.verify(&token.0, &self.0) + public_key.verify(token.0, &self.0) } } diff --git a/src/share/share_link_token.rs b/src/share/share_link_token.rs index ccdfacd..3640cc0 100644 --- a/src/share/share_link_token.rs +++ b/src/share/share_link_token.rs @@ -1,5 +1,3 @@ -use std::convert::Infallible; -use std::str::FromStr; use aes_gcm::aead::rand_core::{CryptoRng, RngCore}; use base64::engine::general_purpose::URL_SAFE_NO_PAD; use base64::{DecodeError, Engine}; @@ -15,7 +13,7 @@ impl SecreteShareLinkToken { Self(token) } pub fn to_base64_url_safe(&self) -> String { - URL_SAFE_NO_PAD.encode(&self.0) + URL_SAFE_NO_PAD.encode(self.0) } pub fn from_base64_url_safe(encoded: &str) -> Result { @@ -39,7 +37,7 @@ impl ShareLinkToken { Self(token) } pub fn to_base64_url_safe(&self) -> String { - URL_SAFE_NO_PAD.encode(&self.0) + URL_SAFE_NO_PAD.encode(self.0) } pub fn from_base64_url_safe(encoded: &str) -> Result { diff --git a/src/share/token_path.rs b/src/share/token_path.rs index 947fdd5..7a9468c 100644 --- a/src/share/token_path.rs +++ b/src/share/token_path.rs @@ -1,8 +1,6 @@ use std::fmt; use std::fmt::{Display, Formatter}; use std::str::FromStr; -use base64::Engine; -use base64::engine::general_purpose::URL_SAFE_NO_PAD; use crate::share::share_link_token::{ShareLinkToken, ShareLinkTokenUnion}; use crate::share::versioning::SharingApiPath; @@ -15,7 +13,7 @@ pub struct TokenPath { impl Display for TokenPath { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let encoded_token = self.token.to_base64_url_safe(); - write!(f, "{}/{}",self.version.to_string(), encoded_token) + write!(f, "{}/{}",self.version, encoded_token) } } diff --git a/src/token/bearer_token.rs b/src/token/bearer_token.rs index a7abdfb..de66482 100644 --- a/src/token/bearer_token.rs +++ b/src/token/bearer_token.rs @@ -9,15 +9,13 @@ impl TryFrom<&str> for BearerToken { type Error = (); fn try_from(value: &str) -> Result { - Ok(Self { - 0: value.to_string(), - }) + Ok(Self(value.to_string())) } } impl From for BearerToken { fn from(value: JwtToken) -> Self { - Self { 0: value } + Self(value) } } diff --git a/src/unix_timestamp.rs b/src/unix_timestamp.rs index cc606ec..2b086df 100644 --- a/src/unix_timestamp.rs +++ b/src/unix_timestamp.rs @@ -28,7 +28,7 @@ impl TryInto for UnixTimestamp { fn try_into(self) -> Result { let temp = SystemTime::from(self.0); - let result: Timestamp = Timestamp::try_from(temp).unwrap(); + let result: Timestamp = Timestamp::from(temp); Ok(result) } } @@ -70,7 +70,7 @@ mod tests { #[test] fn test_from_into_conversions() { let time: UnixTimestamp = UnixTimestamp::default(); - let prost: Timestamp = time.clone().try_into().unwrap(); + let prost: Timestamp = time.try_into().unwrap(); let time2 = UnixTimestamp::try_from(prost).unwrap(); assert_eq!(time, time2) }