use alloc::string::String;
use alloc::vec::Vec;
use sentc_crypto_common::user::{DoneLoginServerOutput, RegisterData, UserPublicKeyData, UserVerifyKeyData};
use sentc_crypto_common::{DeviceId, UserId};
use sentc_crypto_std_keys::core::DeriveMasterKeyForAuth;
use sentc_crypto_std_keys::util::{MasterKeyFormat, PublicKey, SecretKey, SignKey, SymKeyFormatExport, SymmetricKey, VerifyKey};
use sentc_crypto_utils::user;
use serde_json::from_str;
use crate::entities::user::{UserDataExport, UserKeyDataExport};
use crate::keys::std::StdUser;
use crate::{group, SdkError};
pub type StdDeviceKeyDataInt = user::DeviceKeyDataInt<SecretKey, PublicKey, SignKey, VerifyKey>;
pub type StdUserPreVerifyLogin = user::UserPreVerifyLogin<SecretKey, PublicKey, SignKey, VerifyKey>;
pub fn prepare_check_user_identifier_available(user_identifier: &str) -> Result<String, String>
{
Ok(super::user::prepare_check_user_identifier_available(user_identifier)?)
}
pub fn done_check_user_identifier_available(server_output: &str) -> Result<bool, String>
{
Ok(super::user::done_check_user_identifier_available(server_output)?)
}
pub fn generate_user_register_data() -> Result<(String, String), String>
{
Ok(super::user::generate_user_register_data()?)
}
pub fn register_typed(user_identifier: &str, password: &str) -> Result<RegisterData, String>
{
Ok(StdUser::register_typed(user_identifier, password)?)
}
pub fn register(user_identifier: &str, password: &str) -> Result<String, String>
{
Ok(StdUser::register(user_identifier, password)?)
}
pub fn done_register(server_output: &str) -> Result<UserId, String>
{
Ok(super::user::done_register(server_output)?)
}
pub fn prepare_register_device_start(device_identifier: &str, password: &str) -> Result<String, String>
{
Ok(StdUser::prepare_register_device_start(device_identifier, password)?)
}
pub fn done_register_device_start(server_output: &str) -> Result<(), String>
{
Ok(super::user::done_register_device_start(server_output)?)
}
pub fn prepare_register_device(server_output: &str, user_keys: &str, key_session: bool) -> Result<(String, String), String>
{
let user_keys: Vec<SymKeyFormatExport> = from_str(user_keys).map_err(SdkError::JsonParseFailed)?;
let saved_keys = user_keys
.iter()
.map(|k| k.try_into())
.collect::<Result<Vec<SymmetricKey>, _>>()?;
let split_group_keys = group::prepare_group_keys_for_new_member_with_ref(&saved_keys);
let (input, exported_public_key) = StdUser::prepare_register_device(server_output, &split_group_keys, key_session)?;
Ok((
input,
exported_public_key
.to_string()
.map_err(|_e| SdkError::JsonToStringFailed)?,
))
}
pub fn prepare_login_start(user_id: &str) -> Result<String, String>
{
Ok(super::user::prepare_login_start(user_id)?)
}
pub fn prepare_login(user_identifier: &str, password: &str, server_output: &str) -> Result<(String, String, DeriveMasterKeyForAuth), SdkError>
{
StdUser::prepare_login(user_identifier, password, server_output)
}
pub fn done_login(
master_key_encryption: &DeriveMasterKeyForAuth,
auth_key: String,
device_identifier: String,
server_output: DoneLoginServerOutput,
) -> Result<StdUserPreVerifyLogin, SdkError>
{
StdUser::done_login(master_key_encryption, auth_key, device_identifier, server_output)
}
pub fn done_validate_mfa(
master_key_encryption: &str,
auth_key: String,
device_identifier: String,
server_output: &str,
) -> Result<StdUserPreVerifyLogin, SdkError>
{
let master_key_encryption: MasterKeyFormat = master_key_encryption.parse()?;
let master_key_encryption: DeriveMasterKeyForAuth = master_key_encryption.try_into()?;
StdUser::done_validate_mfa(&master_key_encryption, auth_key, device_identifier, server_output)
}
pub fn verify_login(server_output: &str, user_id: UserId, device_id: DeviceId, device_keys: StdDeviceKeyDataInt) -> Result<UserDataExport, String>
{
let out = StdUser::verify_login(server_output, user_id, device_id, device_keys)?;
Ok(out.try_into()?)
}
pub fn done_key_fetch(private_key: &str, server_output: &str) -> Result<UserKeyDataExport, String>
{
let private_key: SecretKey = private_key.parse()?;
let key = StdUser::done_key_fetch(&private_key, server_output)?;
Ok(key.try_into()?)
}
pub fn prepare_user_identifier_update(user_identifier: String) -> Result<String, String>
{
Ok(super::user::prepare_user_identifier_update(user_identifier)?)
}
pub fn prepare_refresh_jwt(refresh_token: String) -> Result<String, String>
{
Ok(super::user::prepare_refresh_jwt(refresh_token)?)
}
pub fn change_password(
old_pw: &str,
new_pw: &str,
server_output_prep_login: &str,
server_output_done_login: DoneLoginServerOutput,
) -> Result<String, SdkError>
{
StdUser::change_password(old_pw, new_pw, server_output_prep_login, server_output_done_login)
}
pub fn reset_password(new_password: &str, decrypted_private_key: &str, decrypted_sign_key: &str) -> Result<String, String>
{
let decrypted_private_key: SecretKey = decrypted_private_key.parse()?;
let decrypted_sign_key: SignKey = decrypted_sign_key.parse()?;
Ok(StdUser::reset_password(
new_password,
&decrypted_private_key,
&decrypted_sign_key,
)?)
}
pub fn create_safety_number(verify_key_1: &str, user_id_1: &str, verify_key_2: Option<&str>, user_id_2: Option<&str>) -> Result<String, String>
{
let verify_key_1 = UserVerifyKeyData::from_string(verify_key_1).map_err(SdkError::JsonParseFailed)?;
let verify_key_2 = match verify_key_2 {
Some(k) => Some(UserVerifyKeyData::from_string(k).map_err(SdkError::JsonParseFailed)?),
None => None,
};
Ok(StdUser::create_safety_number(
&verify_key_1,
user_id_1,
verify_key_2.as_ref(),
user_id_2,
)?)
}
pub fn verify_user_public_key(verify_key: &str, public_key: &str) -> Result<bool, String>
{
let verify_key = UserVerifyKeyData::from_string(verify_key).map_err(SdkError::JsonParseFailed)?;
let public_key = UserPublicKeyData::from_string(public_key).map_err(SdkError::JsonParseFailed)?;
Ok(StdUser::verify_user_public_key(&verify_key, &public_key)?)
}
#[cfg(test)]
mod test
{
extern crate std;
use alloc::string::ToString;
use alloc::vec;
use sentc_crypto_common::group::CreateData;
use sentc_crypto_common::user::{
ChangePasswordData,
RegisterData,
UserDeviceDoneRegisterInput,
UserDeviceRegisterInput,
UserDeviceRegisterOutput,
};
use sentc_crypto_common::ServerOutput;
use serde_json::to_string;
use super::*;
use crate::user::test_fn::{create_user_export, simulate_server_done_login, simulate_server_prepare_login, simulate_verify_login};
#[test]
fn test_register()
{
let username = "admin";
let password = "abc*èéöäüê";
let out = register(username, password).unwrap();
std::println!("{}", out);
}
#[test]
fn test_register_with_generated_data()
{
let (username, password) = generate_user_register_data().unwrap();
register(&username, &password).unwrap();
}
#[test]
fn test_register_and_login()
{
let username = "admin";
let password = "abc*èéöäüê";
let out_string = register(username, password).unwrap();
let out = RegisterData::from_string(&out_string).unwrap();
let server_output = simulate_server_prepare_login(&out.device.derived);
let (_input, auth_key, master_key_encryption_key) = prepare_login(username, password, server_output.as_str()).unwrap();
let server_output = simulate_server_done_login(out);
let done_login = StdUser::done_login(
&master_key_encryption_key, auth_key,
username.to_string(),
server_output,
)
.unwrap();
let server_output = simulate_verify_login(RegisterData::from_string(&out_string).unwrap(), &done_login.challenge);
let _out = verify_login(
&server_output,
done_login.user_id,
done_login.device_id,
done_login.device_keys,
)
.unwrap();
}
#[test]
fn test_change_password()
{
let username = "admin";
let password = "abc*èéöäüê";
let new_password = "abcdfg";
let out = register(username, password).unwrap();
let out_new = RegisterData::from_string(out.as_str()).unwrap();
let out_old = RegisterData::from_string(out.as_str()).unwrap();
let prep_server_output = simulate_server_prepare_login(&out_new.device.derived);
let done_server_output = simulate_server_done_login(out_new);
let pw_change_out = change_password(password, new_password, &prep_server_output, done_server_output).unwrap();
let pw_change_out = ChangePasswordData::from_string(pw_change_out.as_str()).unwrap();
assert_ne!(
pw_change_out.new_client_random_value,
out_old.device.derived.client_random_value
);
assert_ne!(
pw_change_out.new_encrypted_master_key,
out_old.device.master_key.encrypted_master_key
);
}
#[test]
fn test_new_device()
{
let out_string = register("hello", "1234").unwrap();
let out = RegisterData::from_string(out_string.as_str()).unwrap();
let server_output = simulate_server_prepare_login(&out.device.derived);
let (_input, auth_key, master_key_encryption_key) = prepare_login("hello", "1234", server_output.as_str()).unwrap();
let server_output = simulate_server_done_login(out);
let done_login_out = StdUser::done_login(
&master_key_encryption_key, auth_key,
"hello".to_string(),
server_output,
)
.unwrap();
let server_output = simulate_verify_login(
RegisterData::from_string(&out_string).unwrap(),
&done_login_out.challenge,
);
let user = verify_login(
&server_output,
done_login_out.user_id,
done_login_out.device_id,
done_login_out.device_keys,
)
.unwrap();
let device_id = "hello_device";
let device_pw = "12345";
let server_input = prepare_register_device_start(device_id, device_pw).unwrap();
let input: UserDeviceRegisterInput = from_str(&server_input).unwrap();
let server_output = UserDeviceRegisterOutput {
device_id: "abc".to_string(),
token: "1234567890".to_string(),
device_identifier: device_id.to_string(),
public_key_string: input.derived.public_key.to_string(),
keypair_encrypt_alg: input.derived.keypair_encrypt_alg.to_string(),
};
let server_output = ServerOutput {
status: true,
err_msg: None,
err_code: None,
result: Some(server_output),
};
let server_output = to_string(&server_output).unwrap();
done_register_device_start(&server_output).unwrap();
let g_k: SymKeyFormatExport = from_str(&user.user_keys[0].group_key).unwrap();
let user_keys = to_string(&vec![g_k]).unwrap();
let (out, _) = prepare_register_device(&server_output, &user_keys, false).unwrap();
let out: UserDeviceDoneRegisterInput = from_str(&out).unwrap();
let user_keys = &out.user_keys.keys[0];
let out_new_device = RegisterData::from_string(out_string.as_str()).unwrap();
let server_output = simulate_server_prepare_login(&input.derived);
let (_input, auth_key, master_key_encryption_key) = prepare_login(device_id, device_pw, server_output.as_str()).unwrap();
let new_device_register_data = to_string(&RegisterData {
device: input,
group: CreateData {
encrypted_group_key: user_keys.encrypted_group_key.to_string(),
group_key_alg: out_new_device.group.group_key_alg,
encrypted_group_key_alg: user_keys.encrypted_alg.to_string(),
encrypted_private_group_key: out_new_device.group.encrypted_private_group_key,
public_group_key: out_new_device.group.public_group_key,
keypair_encrypt_alg: out_new_device.group.keypair_encrypt_alg,
creator_public_key_id: "abc".to_string(),
encrypted_hmac_key: out_new_device.group.encrypted_hmac_key,
encrypted_hmac_alg: out_new_device.group.encrypted_hmac_alg,
encrypted_sortable_key: out_new_device.group.encrypted_sortable_key,
encrypted_sortable_alg: out_new_device.group.encrypted_sortable_alg,
signed_by_user_id: None,
signed_by_user_sign_key_id: None,
group_key_sig: None,
encrypted_sign_key: out_new_device.group.encrypted_sign_key,
verify_key: out_new_device.group.verify_key,
keypair_sign_alg: out_new_device.group.keypair_sign_alg,
public_key_sig: out_new_device.group.public_key_sig,
},
})
.unwrap();
let server_output = simulate_server_done_login(from_str(&new_device_register_data).unwrap());
let new_device_data = StdUser::done_login(
&master_key_encryption_key,
auth_key,
device_id.to_string(),
server_output,
)
.unwrap();
let server_output = simulate_verify_login(
from_str(&new_device_register_data).unwrap(),
&new_device_data.challenge,
);
let new_device_data = verify_login(
&server_output,
new_device_data.user_id,
new_device_data.device_id,
new_device_data.device_keys,
)
.unwrap();
assert_eq!(user.user_keys[0].group_key, new_device_data.user_keys[0].group_key);
assert_ne!(user.device_keys.private_key, new_device_data.device_keys.private_key);
}
#[test]
fn test_safety_number()
{
let user_1 = create_user_export();
let user_1_id = "abc1";
let user_2 = create_user_export();
let user_2_id = "abc2";
let user_3 = create_user_export();
let user_3_id = "abc3";
let _number_single = create_safety_number(&user_1.user_keys[0].exported_verify_key, &user_1.user_id, None, None).unwrap();
let number = create_safety_number(
&user_1.user_keys[0].exported_verify_key,
user_1_id,
Some(&user_2.user_keys[0].exported_verify_key),
Some(user_2_id),
)
.unwrap();
let number_2 = create_safety_number(
&user_2.user_keys[0].exported_verify_key,
user_2_id,
Some(&user_1.user_keys[0].exported_verify_key),
Some(user_1_id),
)
.unwrap();
assert_eq!(number, number_2);
let number_3 = create_safety_number(
&user_3.user_keys[0].exported_verify_key,
user_3_id,
Some(&user_1.user_keys[0].exported_verify_key),
Some(user_1_id),
)
.unwrap();
assert_ne!(number, number_3);
}
#[test]
fn test_verify_public_key()
{
let user_1 = create_user_export();
let verify = verify_user_public_key(
&user_1.user_keys[0].exported_verify_key,
&user_1.user_keys[0].exported_public_key,
)
.unwrap();
assert!(verify);
}
#[test]
fn test_verify_public_key_with_wrong_key()
{
let user_1 = create_user_export();
let user_2 = create_user_export();
let verify = verify_user_public_key(
&user_1.user_keys[0].exported_verify_key,
&user_2.user_keys[0].exported_public_key,
)
.unwrap();
assert!(!verify);
let verify = verify_user_public_key(
&user_2.user_keys[0].exported_verify_key,
&user_1.user_keys[0].exported_public_key,
)
.unwrap();
assert!(!verify);
}
}