mega-security-rs 0.3.0

An implementation of Mega's security whitepaper
Documentation
use rand::prelude::*;

use rsa::RsaPublicKey;
use sha2::{Digest, Sha256};

use crate::{errors::ClientError, keys::{KeysDecrypted, KeysPayload}, session::{SessionId, SessionIdEncrypted}, utils::{_compute_derived_key, _salt}};

#[derive(Debug, Clone)]
pub struct ClientRegistration {
    pub id: String,
    random_number: Vec<u8>,
    hashed_auth_key: Vec<u8>,
    pub rsa_public_key: RsaPublicKey,
    pub encrypted_keys: KeysPayload,
}

impl ClientRegistration {
    pub fn new_from_creds(id: &str, password: &str, domain: Option<&str>) -> Result<Self, ClientError> {
        let mut rng = rand::thread_rng();

        let mut master_key = [0u8;16];
        rng.fill_bytes(&mut master_key);

        let mut random_value = [0u8;16];
        rng.fill_bytes(&mut random_value);

        let salt = if let Some(d) = domain { 
            _salt(d, &random_value)
        } else {
            _salt(id, &random_value)
        };

        let derived_key = _compute_derived_key(&salt, password);

        let derived_encryption_key = &derived_key[0..16];
        let second_half = &derived_key[17..32];

        let mut auth_key_hasher = Sha256::new();
        auth_key_hasher.update(second_half);
        let hashed_auth_key = &auth_key_hasher.finalize()[..16];

        let (encrypted_keys, rsa_public_key) = KeysPayload::new(&master_key, &derived_encryption_key)?;

        Ok(Self {
            id: id.to_owned(),
            random_number: random_value.to_vec(),
            hashed_auth_key: hashed_auth_key.to_vec(),
            encrypted_keys,
            rsa_public_key,
        })
    }


    pub fn random_number(&self) -> &Vec<u8> {
        &self.random_number
    }

    pub fn hashed_auth_key(&self) -> &Vec<u8> {
        &self.hashed_auth_key
    }
}


#[derive(Debug, Default)]
pub struct AuthClient {
    pub id: String,
    password: String,
    salt: Option<Vec<u8>>,
    derived_encryption_key: Option<Vec<u8>>,
    autentication_key: Option<Vec<u8>>,
    pub decrypted_keys: Option<KeysDecrypted>,
    pub session: Option<SessionId>,
}

impl AuthClient {
    pub fn new_from_creds(id: &str, password: &str) -> Self {
        Self {
            id: id.to_owned(),
            password: password.to_owned(),
            ..Default::default()
        }
    }

    pub fn compute_derived_key(&mut self, salt: &[u8]) {
        let derived_key = _compute_derived_key(salt, &self.password);
        self.salt = Some(salt.to_vec());
        self.derived_encryption_key = Some(derived_key[..16].to_vec());
        self.autentication_key = Some(derived_key[17..32].to_vec());
    }

    pub fn autentication_key(&self) -> &Option<Vec<u8>> {
        &self.autentication_key
    }

    pub fn decrypt_keys(&mut self, mut encrypted_keys: KeysPayload, session_id_enc: SessionIdEncrypted) -> Result<(), ClientError> {
        let dek = if let Some(dek) = &self.derived_encryption_key { dek } 
            else { return Err( ClientError::KeyNotPresent("Derived Encryption Key".to_owned())) } ;


        self.decrypted_keys = 
            Some(
                KeysDecrypted::from_encrypted(
                    &mut encrypted_keys, 
                    dek
                )?
            );

        let uneck = if let Some(uneck) = &self.decrypted_keys { uneck } 
            else { return Err( ClientError::KeyNotPresent("decrypted keys".to_owned())) } ;

        let pk = uneck.rsa.clone();
        self.session = Some(
            SessionId::from_encrypted(
                session_id_enc, 
                &pk
            ));
        Ok(())
    }
}