Skip to main content

TData

Struct TData 

Source
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: u32

Telegram Desktop version stored in the key file’s TDF$ header; TData::save always writes APP_VERSION.

§key_file: String

The data name of the key file, for example DEFAULT_KEY_FILE; TData::set_key_file changes it after checking the name.

§key_data: KeyData

The 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: AuthKey

The local key every other file is encrypted with.

§passcode_key: AuthKey

The 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: i32

The active index stored in the accounts info, 0 when absent.

§performance_mode: bool

TDesktop.kPerformanceMode: when on, TData::save writes no configs file. TData::load turns it on, the default.

Implementations§

Source§

impl TData

Source

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.

Source

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 under create_local_key("", open salt); with one, a 32-byte wrap salt is drawn, the open wrap is null, and the only wrap is a key_data::default_passcode_kdf wrap 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.

Source

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
Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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
Source

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

self is then unchanged.

Source

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.

Source

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.

Source

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§

Source§

impl Clone for TData

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for TData

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.