Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim-Leon committed Nov 25, 2024
1 parent a926fda commit 802cc80
Show file tree
Hide file tree
Showing 20 changed files with 214 additions and 200 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 1 addition & 3 deletions src/bucket/bucket_guid.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
1 change: 0 additions & 1 deletion src/bucket/bucket_path.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
1 change: 0 additions & 1 deletion src/bucket/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
9 changes: 3 additions & 6 deletions src/bucket_search_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,8 @@ pub fn parse_search(search: &str) -> Vec<SearchTokensValue> {
}
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()));
}
}
}
Expand Down Expand Up @@ -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(),
Expand Down
3 changes: 1 addition & 2 deletions src/key/derived_key.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::{default, ops::DerefMut};

use generic_array::GenericArray;
use secrecy::{ExposeSecret, ExposeSecretMut};
Expand All @@ -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::<u8, generic_array::typenum::U32>::default());
pbkdf2::pbkdf2_hmac::<Sha3_256>(&master_key.key.expose_secret(), &bucket_guid.to_bytes(), params
pbkdf2::pbkdf2_hmac::<Sha3_256>(master_key.key.expose_secret(), &bucket_guid.to_bytes(), params
.rounds , secrete.expose_secret_mut());

Self {
Expand Down
68 changes: 37 additions & 31 deletions src/key/master_key.rs
Original file line number Diff line number Diff line change
@@ -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<u8, typenum::U32>,
}

#[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<Self, Infallible>
fn new(argon2: &Argon2, password: impl AsRef<[u8]>, salt: SaltString)
-> Result<Self, MasterKey256Error>
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 })
}
}

Expand All @@ -42,19 +48,19 @@ pub enum MasterKey256ParseError {

}

impl TryInto<pkcs8::PrivateKeyInfo<'_>> for MasterKey256 {
type Error = Infallible;
fn try_into(self) -> Result<pkcs8::PrivateKeyInfo<'static>, Self::Error> {
Ok(PrivateKeyInfo {
algorithm: AlgorithmIdentifier {
oid: (),
parameters: None,
},
private_key: &self.secrete.0,
public_key: None,
})
}
}
//impl TryInto<pkcs8::PrivateKeyInfo<'_>> for MasterKey256 {
// type Error = Infallible;
// fn try_into(self) -> Result<pkcs8::PrivateKeyInfo<'static>, 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<ObjectIdentifier> {
Expand Down
94 changes: 54 additions & 40 deletions src/key/master_key_builder.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -51,7 +47,7 @@ pub struct MasterKeyBuilder {


pub struct SecreteShare {
pub share: Gf256,
pub share: Vec<u8>,
}

pub struct Secretes {
Expand All @@ -63,67 +59,85 @@ pub struct Secretes {
impl MasterKeyBuilder {
pub fn new(params: VerifiableSecretSharingSchemeParams) -> Self {
if params.validate() {
return Self {
Self {
params,
}
} else {
panic!("Invalid secret sharing parameters");
}
}

pub fn combine(&self, secrete_shares: Vec<Gf256>) -> MasterKey256 {
pub fn combine(&self, secrete_shares: Vec<SecreteShare>) -> MasterKey256 {
assert!(
secrete_shares.len() >= self.params.threshold,
"Not enough shares to meet the threshold"
);


// Convert SecreteShare to Vec<Gf256> for reconstruction
let shares: Vec<Vec<u8>> = 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::<Scalar, u8, Vec<u8>>(&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(),
32,
"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 = <NistP256 as p256::elliptic_curve::Curve>::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::<Scalar, u8, Vec<u8>>(
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<SecreteShare> = shares
.into_iter()
.map(|share| SecreteShare { share: share })
.map(|share| SecreteShare { share })
.collect();
let a = generic_array::GenericArray::<u8, generic_array::typenum::U32>::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,
}
}
Expand Down
29 changes: 18 additions & 11 deletions src/key/memory/secure_generic_array.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -28,19 +28,19 @@ where
{
/// Creates a new `SecureGenericArray` with global allocator, no memory specific protection.
pub fn new(inner: GenericArray<T, TLength>) -> 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<TAllocator>(
inner: GenericArray<T, TLength>,
allocator:&TAllocator,
allocator:TAllocator,
) -> Result<Self, SecreteGenericArrayError>
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::<T, &TAllocator>::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)))
}

Expand All @@ -52,14 +52,21 @@ where
) -> Result<Self, SecreteGenericArrayError>
where
TCryptoRng: RngCore + CryptoRng,
TAllocator: Allocator,
T: From<u8>, // Add this bound to allow conversion from u8 to T
T: Default,
TAllocator: Allocator
{
let mut slice = GenericArray::<u8, TLength>::default();
rng.fill_bytes(&mut slice);
Ok(
Self::new_in(slice, allocator)?
)
let mut array = GenericArray::<T, TLength>::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)
}
}

Expand Down
6 changes: 0 additions & 6 deletions src/key/mod.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
Loading

0 comments on commit 802cc80

Please sign in to comment.