#[cfg(not(feature = "rust"))]
mod file;
#[cfg(feature = "rust")]
mod file_rust;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use base64ct::{Base64, Encoding};
use sentc_crypto_common::file::{BelongsToType, FileHead, FileNameUpdate, FileRegisterInput, FileRegisterOutput};
use sentc_crypto_common::user::UserVerifyKeyData;
use sentc_crypto_common::{FileId, FileSessionId};
use sentc_crypto_core::SymKey;
#[cfg(not(feature = "rust"))]
pub use self::file::{
decrypt_file_part,
decrypt_file_part_start,
done_register_file,
encrypt_file_part,
encrypt_file_part_start,
prepare_file_name_update,
prepare_register_file,
};
#[cfg(feature = "rust")]
pub use self::file_rust::{
decrypt_file_part,
decrypt_file_part_start,
done_register_file,
encrypt_file_part,
encrypt_file_part_start,
prepare_file_name_update,
prepare_register_file,
};
use crate::crypto::{put_head_and_encrypted_data_internally, sign_internally, split_head_and_encrypted_data_internally, verify_internally};
use crate::entities::keys::{SignKeyFormatInt, SymKeyFormatInt};
use crate::util::public::handle_server_response;
use crate::{crypto, SdkError};
fn prepare_register_file_internally(
master_key_id: String,
key: &SymKeyFormatInt,
encrypted_content_key: String,
belongs_to_id: Option<String>,
belongs_to_type: BelongsToType,
file_name: Option<String>,
) -> Result<(String, Option<String>), SdkError>
{
let encrypted_key_alg = sentc_crypto_core::getting_alg_from_sym_key(&key.key);
let (belongs_to_type, belongs_to_id) = match belongs_to_type {
BelongsToType::None => (belongs_to_type, None),
_ => {
if belongs_to_id.is_none() {
(BelongsToType::None, None)
} else {
(belongs_to_type, belongs_to_id)
}
},
};
let encrypted_file_name = match file_name {
None => None,
Some(f) => {
Some(crypto::encrypt_string_symmetric_internally(key, &f, None)?)
},
};
Ok((
serde_json::to_string(&FileRegisterInput {
master_key_id,
encrypted_key: encrypted_content_key,
belongs_to_id,
belongs_to_type,
encrypted_file_name: encrypted_file_name.clone(),
encrypted_key_alg: encrypted_key_alg.to_string(),
})
.map_err(|_e| SdkError::JsonToStringFailed)?,
encrypted_file_name,
))
}
fn done_register_file_internally(server_output: &str) -> Result<(FileId, FileSessionId), SdkError>
{
let out: FileRegisterOutput = handle_server_response(server_output)?;
Ok((out.file_id, out.session_id))
}
fn prepare_file_name_update_internally(key: &SymKeyFormatInt, file_name: Option<String>) -> Result<String, SdkError>
{
let encrypted_file_name = match file_name {
None => None,
Some(f) => {
Some(crypto::encrypt_string_symmetric_internally(key, &f, None)?)
},
};
serde_json::to_string(&FileNameUpdate {
encrypted_file_name,
})
.map_err(|_e| SdkError::JsonToStringFailed)
}
fn encrypt_file_part_start_internally(key: &SymKeyFormatInt, part: &[u8], sign_key: Option<&SignKeyFormatInt>)
-> Result<(Vec<u8>, SymKey), SdkError>
{
encrypt_file_part_internally(&key.key, part, sign_key)
}
fn encrypt_file_part_internally(pre_content_key: &SymKey, part: &[u8], sign_key: Option<&SignKeyFormatInt>) -> Result<(Vec<u8>, SymKey), SdkError>
{
let (encrypted_key, sym_key_alg, file_key) = sentc_crypto_core::crypto::generate_symmetric_with_master_key(pre_content_key)?;
let encrypted_key_string = Base64::encode_string(&encrypted_key);
let mut encrypted_part = sentc_crypto_core::crypto::encrypt_symmetric(&file_key, part)?;
let sign = if let Some(sk) = sign_key {
let (sign_head, data_with_sign) = sign_internally(sk, &encrypted_part)?;
encrypted_part = data_with_sign;
Some(sign_head)
} else {
None
};
let file_head = FileHead {
key: encrypted_key_string,
sign,
sym_key_alg: sym_key_alg.to_string(),
};
Ok((
put_head_and_encrypted_data_internally(&file_head, &encrypted_part)?,
file_key,
))
}
fn decrypt_file_part_start_internally(
key: &SymKeyFormatInt,
part: &[u8],
verify_key: Option<&UserVerifyKeyData>,
) -> Result<(Vec<u8>, SymKey), SdkError>
{
decrypt_file_part_internally(&key.key, part, verify_key)
}
fn decrypt_file_part_internally(pre_content_key: &SymKey, part: &[u8], verify_key: Option<&UserVerifyKeyData>)
-> Result<(Vec<u8>, SymKey), SdkError>
{
let (head, encrypted_part) = split_head_and_encrypted_data_internally::<FileHead>(part)?;
let encrypted_key = Base64::decode_vec(&head.key).map_err(|_| SdkError::DecodeEncryptedDataFailed)?;
let file_key = sentc_crypto_core::crypto::get_symmetric_key_from_master_key(pre_content_key, &encrypted_key, &head.sym_key_alg)?;
let decrypted_part = match &head.sign {
None => sentc_crypto_core::crypto::decrypt_symmetric(&file_key, encrypted_part)?, Some(h) => {
match verify_key {
None => {
let (_, encrypted_data_without_sig) = sentc_crypto_core::crypto::split_sig_and_data(h.alg.as_str(), encrypted_part)?;
sentc_crypto_core::crypto::decrypt_symmetric(&file_key, encrypted_data_without_sig)?
},
Some(vk) => {
let encrypted_data_without_sig = verify_internally(vk, encrypted_part, h)?;
sentc_crypto_core::crypto::decrypt_symmetric(&file_key, encrypted_data_without_sig)?
},
}
},
};
Ok((decrypted_part, file_key))
}