pub struct Device { /* private fields */ }
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§
Source§impl Device
impl Device
Sourcepub async fn request_verification(&self) -> Result<VerificationRequest>
pub async fn request_verification(&self) -> Result<VerificationRequest>
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?;
}
Sourcepub async fn request_verification_with_methods(
&self,
methods: Vec<VerificationMethod>,
) -> Result<VerificationRequest>
pub async fn request_verification_with_methods( &self, methods: Vec<VerificationMethod>, ) -> Result<VerificationRequest>
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?;
}
Sourcepub async fn start_verification(&self) -> Result<SasVerification>
👎Deprecated since 0.4.0: directly starting a verification is deprecated in the spec. Users should instead use request_verification()
pub async fn start_verification(&self) -> Result<SasVerification>
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?;
}
Sourcepub async fn verify(&self) -> Result<(), ManualVerifyError>
pub async fn verify(&self) -> Result<(), ManualVerifyError>
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?;
}
Sourcepub fn is_verified(&self) -> bool
pub fn is_verified(&self) -> bool
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.is_verified() {
println!(
"Device {} of user {} is verified",
device.device_id(),
device.user_id(),
);
} else {
println!(
"Device {} of user {} is not verified",
device.device_id(),
device.user_id(),
);
}
}
Sourcepub fn is_verified_with_cross_signing(&self) -> bool
pub fn is_verified_with_cross_signing(&self) -> bool
Is the device considered to be verified with cross-signing.
A device is considered to be verified if it’s signed by the appropriate cross-signing key.
§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.is_verified_with_cross_signing() {
println!(
"Device {} of user {} is verified with cross-signing",
device.device_id(),
device.user_id()
);
} else {
println!(
"Device {} of user {} is not verified with cross-signing",
device.device_id(),
device.user_id()
);
}
}
Sourcepub async fn set_local_trust(
&self,
trust_state: LocalTrust,
) -> Result<(), CryptoStoreError>
pub async fn set_local_trust( &self, trust_state: LocalTrust, ) -> Result<(), CryptoStoreError>
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.
Sourcepub fn is_cross_signed_by_owner(&self) -> bool
pub fn is_cross_signed_by_owner(&self) -> bool
Is the device cross-signed by its own user.
Methods from Deref<Target = DeviceData>§
Sourcepub fn display_name(&self) -> Option<&str>
pub fn display_name(&self) -> Option<&str>
Get the human readable name of the device.
Sourcepub fn get_key(&self, algorithm: DeviceKeyAlgorithm) -> Option<&DeviceKey>
pub fn get_key(&self, algorithm: DeviceKeyAlgorithm) -> Option<&DeviceKey>
Get the key of the given key algorithm belonging to this device.
Sourcepub fn curve25519_key(&self) -> Option<Curve25519PublicKey>
pub fn curve25519_key(&self) -> Option<Curve25519PublicKey>
Get the Curve25519 key of the given device.
Sourcepub fn ed25519_key(&self) -> Option<Ed25519PublicKey>
pub fn ed25519_key(&self) -> Option<Ed25519PublicKey>
Get the Ed25519 key of the given device.
Sourcepub fn keys(
&self,
) -> &BTreeMap<OwnedKeyId<DeviceKeyAlgorithm, DeviceId>, DeviceKey>
pub fn keys( &self, ) -> &BTreeMap<OwnedKeyId<DeviceKeyAlgorithm, DeviceId>, DeviceKey>
Get a map containing all the device keys.
Sourcepub fn signatures(&self) -> &Signatures
pub fn signatures(&self) -> &Signatures
Get a map containing all the device signatures.
Sourcepub fn local_trust_state(&self) -> LocalTrust
pub fn local_trust_state(&self) -> LocalTrust
Get the trust state of the device.
Sourcepub fn is_locally_trusted(&self) -> bool
pub fn is_locally_trusted(&self) -> bool
Is the device locally marked as trusted.
Sourcepub fn is_blacklisted(&self) -> bool
pub fn is_blacklisted(&self) -> bool
Is the device locally marked as blacklisted.
Blacklisted devices won’t receive any group sessions.
Sourcepub fn was_withheld_code_sent(&self) -> bool
pub fn was_withheld_code_sent(&self) -> bool
Returns true if the m.no_olm
withheld code was already sent to this
device.
Sourcepub fn algorithms(&self) -> &[EventEncryptionAlgorithm]
pub fn algorithms(&self) -> &[EventEncryptionAlgorithm]
Get the list of algorithms this device supports.
Sourcepub fn supports_olm(&self) -> bool
pub fn supports_olm(&self) -> bool
Does this device support any of our known Olm encryption algorithms.
Sourcepub fn olm_session_config(&self) -> SessionConfig
pub fn olm_session_config(&self) -> SessionConfig
Get the optimal SessionConfig
for this device.
Sourcepub fn is_deleted(&self) -> bool
pub fn is_deleted(&self) -> bool
Is the device deleted.
Sourcepub fn as_device_keys(&self) -> &DeviceKeys
pub fn as_device_keys(&self) -> &DeviceKeys
Return the device keys
Sourcepub fn first_time_seen_ts(&self) -> MilliSecondsSinceUnixEpoch
pub fn first_time_seen_ts(&self) -> MilliSecondsSinceUnixEpoch
Get the local timestamp of when this device was first persisted, in milliseconds since epoch (client local time).
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Device
impl !RefUnwindSafe for Device
impl Send for Device
impl Sync for Device
impl Unpin for Device
impl !UnwindSafe for Device
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, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
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