pub struct TData {
pub app_version: u32,
pub key_file: String,
pub key_data: KeyData,
pub local_key: AuthKey,
pub passcode_key: AuthKey,
pub accounts: Vec<Account>,
pub active_index: i32,
pub performance_mode: bool,
/* private fields */
}Expand description
A tdata folder, loaded from disk or created for writing.
Debug prints key ids only, never key material, and never the passcode.
Fields§
§app_version: u32Telegram Desktop version stored in the key file’s TDF$ header;
TData::save always writes APP_VERSION.
key_file: StringThe data name of the key file, for example DEFAULT_KEY_FILE;
TData::set_key_file changes it after checking the name.
key_data: KeyDataThe parsed key file; only the live passcode wraps are kept, so stale
wraps are not written back. TData::save writes it
with a freshly encrypted accounts info, migrated first when it has
the legacy layout.
local_key: AuthKeyThe local key every other file is encrypted with.
passcode_key: AuthKeyThe open or passcode key the local key was wrapped under.
accounts: Vec<Account>The accounts that loaded, in accounts-info order without duplicates.
active_index: i32The active index stored in the accounts info, 0 when absent.
performance_mode: boolTDesktop.kPerformanceMode: when on, TData::save writes no
configs file. TData::load turns it on, the default.
Implementations§
Source§impl TData
impl TData
Sourcepub const MAX_ACCOUNTS: usize = 6
pub const MAX_ACCOUNTS: usize = 6
Most accounts one folder holds (TDesktop.kMaxAccounts);
TData::add_account refuses more. TData::load still reads a
folder that lists more.
Sourcepub fn new(
accounts: Vec<Account>,
passcode: &[u8],
performance_mode: bool,
rng: &mut dyn FnMut(&mut [u8]),
) -> Result<Self>
pub fn new( accounts: Vec<Account>, passcode: &[u8], performance_mode: bool, rng: &mut dyn FnMut(&mut [u8]), ) -> Result<Self>
Creates a folder for accounts the way SaveTData does for a
TDesktop that was not loaded (__generateLocalKey), drawing random
bytes from rng in draw_plan order.
- Performance mode on and an empty passcode: the fixed performance-mode local key and open wrap; nothing is drawn.
- Otherwise: a 256-byte random pass and a 32-byte salt make the local
key (
create_local_key(pass, salt)), then a 32-byte open salt is drawn. Without a passcode the local key is wrapped undercreate_local_key("", open salt); with one, a 32-byte wrap salt is drawn, the open wrap is null, and the only wrap is akey_data::default_passcode_kdfwrap of generation 1, committed. Each wrap draws its 12 padding bytes.
The folder uses DEFAULT_KEY_FILE and NEW_FOLDER_ACTIVE_INDEX;
both fields can be changed before saving.
§Errors
As key_data::create_passcode_key and key_data::wrap_local_key.
Sourcepub fn save(
&self,
dir: impl AsRef<Path>,
rng: &mut dyn FnMut(&mut [u8]),
) -> Result<()>
pub fn save( &self, dir: impl AsRef<Path>, rng: &mut dyn FnMut(&mut [u8]), ) -> Result<()>
Writes the folder into dir, drawing every padding from rng in
draw_plan order.
Per account, in order: <folder>/maps (two null arrays and the
encrypted map, see map::MapData::encode_entries), then, with
performance mode off, <folder>/configs (the loaded config or
account::MTP_CONFIG_PRODUCTION), then the <folder>s MTP data
(Account::encode_mtp_data). Last the key file: the open salt, the
open wrap, the accounts info (AccountsInfo::encode) encrypted
under the local key, and the 7.3 trailer. Every file carries
APP_VERSION.
A legacy key file (no trailer) is migrated first: before any other
draw, the same
local key is wrapped in a fresh 7.3 key file under the passcode this
TData was loaded or created with, as TData::new describes
after the local key (open salt, then wrap salt with a passcode, then
the wrap padding). The account files stay valid. self is not
changed, so every save of a still-legacy TData migrates afresh;
TData::migrate first keeps one migration for every later save.
§Errors
Error::SaveFailedwhen there is no account, or when an account map encodes to nothing, which cannot be encrypted.- As
key_data::create_passcode_keywhen migrating under a passcode. Error::Iowhen a directory or file cannot be written.Error::QDataStreamFailedwhen a blob does not fit au32length.
Sourcepub fn save_random(&self, dir: impl AsRef<Path>) -> Result<()>
pub fn save_random(&self, dir: impl AsRef<Path>) -> Result<()>
TData::save with padding from the operating system’s CSPRNG.
§Errors
Error::Io when the system random source fails, otherwise as
TData::save.
Sourcepub fn new_with_draws(
accounts: Vec<Account>,
passcode: &[u8],
performance_mode: bool,
active_index: i32,
draws: DrawSource,
) -> Result<Self>
pub fn new_with_draws( accounts: Vec<Account>, passcode: &[u8], performance_mode: bool, active_index: i32, draws: DrawSource, ) -> Result<Self>
TData::new with its draws from draws, storing active_index
(NEW_FOLDER_ACTIVE_INDEX when the caller has none).
A failed or mismatched draw leaves the keys unspecified, so the folder
is discarded and the draw failure is returned, before any failure of
TData::new itself.
§Errors
As DrawSource::finish, otherwise as TData::new.
Sourcepub fn save_with_draws(
&self,
dir: impl AsRef<Path>,
performance_mode: Option<bool>,
draws: DrawSource,
) -> Result<()>
pub fn save_with_draws( &self, dir: impl AsRef<Path>, performance_mode: Option<bool>, draws: DrawSource, ) -> Result<()>
TData::save with its padding from draws, and with
performance_mode, when given, in place of
TData::performance_mode for this save only (on: no configs
files are written). self is not changed.
The operating system source fails fast as TData::save_random
does. A replay runs the whole save; on a mismatch the written files
are not usable and the draw failure is returned, before any failure
of the save itself.
§Errors
As DrawSource::finish, otherwise as TData::save_random.
Sourcepub fn migrate_with_draws(&mut self, draws: DrawSource) -> Result<bool>
pub fn migrate_with_draws(&mut self, draws: DrawSource) -> Result<bool>
TData::migrate with its draws from draws. A failed or
mismatched draw leaves the new wrap unspecified, so self stays as
it was and the draw failure is returned.
§Errors
As DrawSource::finish, otherwise as TData::migrate; self is
then unchanged.
Sourcepub fn migrate(&mut self, rng: &mut dyn FnMut(&mut [u8])) -> Result<bool>
pub fn migrate(&mut self, rng: &mut dyn FnMut(&mut [u8])) -> Result<bool>
Installs 7.3 key data in place of a legacy key file (no trailer),
drawing from rng exactly what TData::save draws to migrate, and
returns whether it did. The local key and the accounts stay as they
are; the passcode key becomes the new wrap key, and the stored
accounts info, still valid under the same local key, is kept.
Later saves then write this key data instead of migrating afresh, so two saves with the same padding write the same files. A key file that already has the 7.3 layout is left alone and nothing is drawn.
§Errors
As key_data::create_passcode_key when migrating under a
passcode; self is then unchanged.
Sourcepub fn load(
dir: impl AsRef<Path>,
passcode: &[u8],
key_file: Option<&str>,
) -> Result<Self>
pub fn load( dir: impl AsRef<Path>, passcode: &[u8], key_file: Option<&str>, ) -> Result<Self>
Loads the folder dir (TDesktop.__loadFromTData).
key_file defaults to DEFAULT_KEY_FILE. Each listed index is
loaded once; negative indices are skipped, and an account whose files
fail to read is skipped silently.
§Errors
- As
tdf::readandKeyData::parsefor the key file. - As
key_data::open_local_keyandkey_data::decrypt_accounts_info; a wrong passcode isError::BadDecryptKey. Error::AuthKeyNotFoundwhen no account loads.
Sourcepub fn set_accounts(&mut self, accounts: Vec<Account>) -> Result<()>
pub fn set_accounts(&mut self, accounts: Vec<Account>) -> Result<()>
Replaces the accounts later saves write, keeping the local key, the
key data with its salts, and the active index, so an edited
accounts list is written under the loaded local key.
Up to TData::MAX_ACCOUNTS accounts are accepted, or as many as
TData::load loaded when that is more, so a folder that lists more
than six saves back under the same local key.
§Errors
Error::MaxAccountLimitfor more accounts than that limit.Error::SaveFailedwhen two accounts share an index, whose files one save would overwrite.
self is then unchanged.
Sourcepub fn add_account(
&mut self,
user_id: u64,
main_dc: i32,
auth_key: AuthKey,
) -> Result<i32>
pub fn add_account( &mut self, user_id: u64, main_dc: i32, auth_key: AuthKey, ) -> Result<i32>
Adds an account with auth_key as the key of main_dc, as
Account.FromTelethon adds one to an owner: it gets the map of
MapData::new_account and no config,
and it is appended (_addSingleAccount). The active index is not
changed, so TData::main_account stays the first account of a
folder that had none. Returns the new index.
The index is the lowest one in 0..MAX_ACCOUNTS that no account
holds, tdesktop’s own rule. The account count is not used as the
index: with loaded indices [0, 2] it would give the new account 2,
whose files would overwrite an existing one; here the new account
gets 1. Without gaps both rules agree.
§Errors
Error::MaxAccountLimit when the folder already holds
TData::MAX_ACCOUNTS accounts or every index below it is taken
(You can't have more than 6 accounts in one TDesktop client);
self is then unchanged.
Sourcepub fn set_key_file(&mut self, name: &str) -> Result<()>
pub fn set_key_file(&mut self, name: &str) -> Result<()>
Changes the data name of the key file, as
SaveTData(keyFile=name) does: TData::save then writes
key_<name>s and every account under the data name
account::data_name(name, index).
§Errors
Error::SaveFailed when name is empty; self is then unchanged.
Sourcepub fn main_account(&self) -> Option<&Account>
pub fn main_account(&self) -> Option<&Account>
The main account: the one whose index is the active index, else the
first one; None only when TData::accounts was emptied.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for TData
impl RefUnwindSafe for TData
impl Send for TData
impl Sync for TData
impl Unpin for TData
impl UnsafeUnpin for TData
impl UnwindSafe for TData
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more