pub struct Device { /* private fields */ }
Available on crate feature e2e-encryption only.
Expand description

A device represents a E2EE capable client or device of an user.

A Device is backed by device keys that are uploaded to the server.

The device keys for our own device will be automatically uploaded by the SDK and the private parts of our device keys never leave this device.

Device keys consist of an Ed25519 keypair and a Curve25519 keypair. Only the public parts of those keypairs will be uploaded to the server.

                ┌──────────────────────────────────┐
                │              Device              │
                ├──────────────────────────────────┤
                │            Device Keys           │
                ├────────────────┬─────────────────┤
                │   Ed25519 Key  │  Curve25519 Key │
                └────────────────┴─────────────────┘

The Ed25519 key will be used to uniquely identify the Device while the Curve25519 key is used to establish 1-to-1 encrypted communication channels between two devices.

Implementations

Request an interactive verification with this Device.

Returns a VerificationRequest object that can be used to control the verification flow.

The default methods that are supported are m.sas.v1 and m.qr_code.show.v1, if this isn’t desirable the request_verification_with_methods() method can be used to override this. m.qr_code.show.v1 is only available if the qrcode feature is enabled, which it is by default.

Examples
let device = client.encryption().get_device(alice, device_id!("DEVICEID")).await?;

if let Some(device) = device {
    let verification = device.request_verification().await?;
}

Request an interactive verification with this Device.

Returns a VerificationRequest object that can be used to control the verification flow.

Arguments
  • methods - The verification methods that we want to support. Must be non-empty.
Panics

This method will panic if methods is empty.

Examples
let device = client.encryption().get_device(alice, device_id!("DEVICEID")).await?;

// We don't want to support showing a QR code, we only support SAS
// verification
let methods = vec![VerificationMethod::SasV1];

if let Some(device) = device {
    let verification = device.request_verification_with_methods(methods).await?;
}
👎 Deprecated since 0.4.0:

directly starting a verification is deprecated in the spec. Users should instead use request_verification()

Start an interactive verification with this Device

Returns a SasVerification object that represents the interactive verification flow.

This method has been deprecated in the spec and the request_verification() method should be used instead.

Examples
let device = client.encryption().get_device(alice, device_id!("DEVICEID")).await?;

if let Some(device) = device {
    let verification = device.start_verification().await?;
}

Manually verify this device.

This method will attempt to sign the device using our private cross signing key.

This method will always fail if the device belongs to someone else, we can only sign our own devices.

It can also fail if we don’t have the private part of our self-signing key.

The state of our private cross signing keys can be inspected using the Encryption::cross_signing_status() method.

Problems of manual verification

Manual verification may be more convenient to use, i.e. both devices need to be online and available to interactively verify each other. Despite the convenience, interactive verifications should be generally preferred. Manually verifying a device won’t notify the other device, the one being verified, that they should also verify us. This means that device A will consider device B to be verified, but not the other way around.

Examples
let device = client.encryption().get_device(alice, device_id!("DEVICEID")).await?;

if let Some(device) = device {
    device.verify().await?;
}

Is the device considered to be verified.

A device is considered to be verified, either if it’s locally marked as such, or if it’s signed by the appropriate cross signing key. Our own device, is always implicitly verified.

Local trust

Local trust can be established using the Device::set_local_trust() method or it will be established if we interactively verify the device using Device::request_verification().

Note: The concept of local trust is largely deprecated because it can’t be shared with other devices. Every device needs to verify all the other devices it communicates to. Because this becomes quickly unsustainable verification has migrated to cross signing verification.

Cross signing verification

Cross signing verification uses signatures over devices and user identities to check if a device is considered to be verified. The signatures can be uploaded to the homeserver, this allows us to share the verification state with other devices. Devices only need to verify a user identity, if the user identity has verified and signed the device we can consider the device to be verified as well.

Devices are usually cross signing verified using interactive verification, which can be started using the Device::request_verification() method.

A Device can also be manually signed using the Device::verify() method, this works only for devices belonging to our own user.

Do note that the device that is being manually signed will not trust our own user identity like it would if we interactively verify the device. Such a device can mark our own user as verified using the UserIdentity::verify() method.

Verification of devices belonging to our own user.

If the device belongs to our own user, the device will be considered to be verified if:

  • The device has been signed by our self-signing key
  • Our own user identity is considered to be verified

In other words we need to find a valid signature chain from our user identity to the device:

         ┌─────────────────────────────────────┐    ┌─────────────┐
         │           Own User Identity         │    │   Device    │
         ├──────────────────┬──────────────────┤───►├─────────────┤
         │    Master Key    │ Self-signing Key │    │ Device Keys │
         └──────────────────┴──────────────────┘    └─────────────┘
Verification of devices belonging to other users.

If the device belongs to some other user it will be considered to be verified if:

  • The device has been signed by the user’s self-signing key
  • The user’s master-signing key has been signed by our own user-signing key, i.e. our own identity trusts the other users identity.
  • Our own user identity is considered to be verified
            ┌─────────────────────────────────────┐
            │           Own User Identity         │
            ├──────────────────┬──────────────────┤─────┐
            │    Master Key    │ User-signing Key │     │
            └──────────────────┴──────────────────┘     │
    ┌───────────────────────────────────────────────────┘
    │
    │       ┌─────────────────────────────────────┐    ┌─────────────┐
    │       │             User Identity           │    │   Device    │
    └──────►├──────────────────┬──────────────────┤───►│─────────────│
            │    Master Key    │ Self-signing Key │    │ Device Keys │
            └──────────────────┴──────────────────┘    └─────────────┘
Examples

Let’s check if a device is verified:

let device = client.encryption().get_device(alice, device_id!("DEVICEID")).await?;

if let Some(device) = device {
    if device.verified() {
        println!(
            "Device {} of user {} is verified",
            device.device_id().as_str(), device.user_id().as_str()
        );
    } else {
        println!(
            "Device {} of user {} is not verified",
            device.device_id().as_str(), device.user_id().as_str()
        );
    }
}

Set the local trust state of the device to the given state.

This won’t affect any cross signing verification state, this only sets a flag marking to have the given trust state.

Arguments
  • trust_state - The new trust state that should be set for the device.

Methods from Deref<Target = ReadOnlyDevice>

The user id of the device owner.

The unique ID of the device.

Get the human readable name of the device.

Get the key of the given key algorithm belonging to this device.

Get the Curve25519 key of the given device.

Get the Ed25519 key of the given device.

Get a map containing all the device keys.

Get a map containing all the device signatures.

Get the trust state of the device.

Is the device locally marked as trusted.

Is the device locally marked as blacklisted.

Blacklisted devices won’t receive any group sessions.

Get the list of algorithms this device supports.

Is the device deleted.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

The resulting type after dereferencing.

Dereferences the value.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more

Instruments this type with the current Span, returning an Instrumented wrapper. Read more

Calls U::from(self).

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

The alignment of pointer.

The type for initializers.

Initializes a with the given initializer. Read more

Dereferences the given pointer. Read more

Mutably dereferences the given pointer. Read more

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

Should always be Self

The resulting type after obtaining ownership.

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

🔬 This is a nightly-only experimental API. (toowned_clone_into)

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

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more