Skip to main content

Kek

Struct Kek 

Source
pub struct Kek(/* private fields */);
Expand description

库主密钥(Key Encryption Key)。

由 Argon2id(密码, vault_salt) 派生,每密码每会话只应派生一次, 之后用 Kek::derive_slot_key 等方法为每个文件微秒级派生子密钥。

Implementations§

Source§

impl Kek

Source

pub const fn from_key(key: SecretKey) -> Self

由已有的 32 字节密钥材料构造(如从 OS 密钥库取出的设备密钥、或恢复码)。

Source

pub const fn as_key(&self) -> &SecretKey

借出底层密钥。

Source

pub fn duplicate(&self) -> Self

显式复制。

命名与 SecretKey::duplicate 一致,刻意不实现 Clone——这样审计时 能搜出所有 KEK 复制点。扫描器需要它把会话缓存中的 KEK 传给解包函数。

Source

pub fn from_password( password: &[u8], vault_salt: &[u8], params: Argon2Params, ) -> Result<Self>

用 Argon2id 从密码派生 KEK。

§开销

这是故意慢的操作(默认参数约 180 ms)。调用方必须缓存结果, 不得在循环中对每个文件重复调用。

§Errors

Argon2 参数非法(如内存成本过小)时返回 Error::KeyDerivation。

Source

pub fn derive_dirname_key( &self, vault_salt: &[u8; 16], info: &[u8], ) -> SecretKey

派生 vault 级的目录名加密密钥(树形模式,文档 05 §3.3)。

salt = vault_salt,info 由调用方给出(见 crate::dirname::DirnameKey::derive)。

§为什么 salt 是 vault_salt 而不是 file_uuid

目录名不属于任何单个文件,没有 file_uuid 可用。用 vault_salt 的 副作用是目录结构的可见性绑定整个 vault:能解开 vault 的任一 密码都能看到完整目录树,无法按 slot 区分权限。这是树形模式的固有 约束,UI 必须告知用户。

Source

pub fn derive_slot_key( &self, file_uuid: &[u8; 16], slot_index: u16, ) -> SecretKey

派生第 slot_index 个 key slot 的包裹密钥。

info = "omy/v1/slot" || u16le(slot_index),salt = file_uuid

Source

pub fn fingerprint(&self, vault_salt: &[u8; 16]) -> [u8; 32]

派生该 KEK 的会话内指纹,用于判断两个 KEK 是否相同。

§为什么需要它

会话要同时装多个密码,就必须回答「刚输的这个,是不是已经装过的那个」。 直接比较 KEK 字节是可以的,但那要求把密钥本身搬来搬去做相等比较; 而按名字比较又不成立——同一个密码可以被起两个名字,不同密码也可以 重名(上一轮「label 让同一个密码被算成两条凭据」正是后者)。

§为什么不能落盘

指纹是密码的稳定标识:同一密码在同一 vault 下恒为同一值。写进 磁盘就等于给攻击者一个离线可比对的口令哈希——他能据此判断两个库是不是 同一个密码、能拿字典逐个比对候选密码,而 Argon2 那几百毫秒的代价 在这里完全不起作用(KEK 已经是派生结果,指纹只是一次 HKDF)。

所以它只允许在内存里存在,不得写入任何文件、日志或 IPC 响应。

§为什么 salt 是 vault_salt

让指纹天然绑定 vault。同一密码在不同 vault 下 KEK 本就不同,指纹也就 不同——这与缓存键必须含 vault_salt 是同一个道理,避免跨库误判成 「已经装过了」。

Trait Implementations§

Source§

impl Debug for Kek

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Forget for Kek

§

impl Freeze for Kek

§

impl RefUnwindSafe for Kek

§

impl Send for Kek

§

impl Sync for Kek

§

impl Unpin for Kek

§

impl UnsafeUnpin for Kek

§

impl UnwindSafe for Kek

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> 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> Same for T

Source§

type Output = T

Should always be Self
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.