From 0fa6ff69554b5de0728af3aa161696fa068bffa8 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 16 Aug 2022 11:29:27 +0200 Subject: [PATCH] feat(crypto-js): Add `DeviceKeyId`, `DeviceKeyAlgorith` and `DeviceKeyAlgorithmName`. --- .../matrix-sdk-crypto-js/src/identifiers.rs | 103 ++++++++++++++++++ .../tests/identifiers.test.js | 48 +++++++- 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/bindings/matrix-sdk-crypto-js/src/identifiers.rs b/bindings/matrix-sdk-crypto-js/src/identifiers.rs index e594d1a6a..e0bf6e7c9 100644 --- a/bindings/matrix-sdk-crypto-js/src/identifiers.rs +++ b/bindings/matrix-sdk-crypto-js/src/identifiers.rs @@ -88,6 +88,109 @@ impl DeviceId { } } +/// A Matrix device key ID. +/// +/// A key algorithm and a device ID, combined with a ‘:’. +#[wasm_bindgen] +#[derive(Debug, Clone)] +pub struct DeviceKeyId { + pub(crate) inner: ruma::OwnedDeviceKeyId, +} + +impl From for DeviceKeyId { + fn from(inner: ruma::OwnedDeviceKeyId) -> Self { + Self { inner } + } +} + +#[wasm_bindgen] +impl DeviceKeyId { + /// Parse/validate and create a new `DeviceKeyId`. + #[wasm_bindgen(constructor)] + pub fn new(id: String) -> Result { + Ok(Self::from(ruma::DeviceKeyId::parse(id.as_str())?)) + } + + /// Returns key algorithm of the device key ID. + #[wasm_bindgen(getter)] + pub fn algorithm(&self) -> DeviceKeyAlgorithm { + self.inner.algorithm().into() + } + + /// Returns device ID of the device key ID. + #[wasm_bindgen(getter, js_name = "deviceId")] + pub fn device_id(&self) -> DeviceId { + self.inner.device_id().to_owned().into() + } + + /// Return the device key ID as a string. + #[wasm_bindgen(js_name = "toString")] + #[allow(clippy::inherent_to_string)] + pub fn to_string(&self) -> String { + self.inner.to_string() + } +} + +/// The basic key algorithms in the specification. +#[wasm_bindgen] +pub struct DeviceKeyAlgorithm { + inner: ruma::DeviceKeyAlgorithm, +} + +impl From for DeviceKeyAlgorithm { + fn from(inner: ruma::DeviceKeyAlgorithm) -> Self { + Self { inner } + } +} + +#[wasm_bindgen] +impl DeviceKeyAlgorithm { + /// Read the device key algorithm's name. If the name is + /// `Unknown`, one may be interested by the `to_string` method to + /// read the original name. + #[wasm_bindgen(getter)] + pub fn name(&self) -> DeviceKeyAlgorithmName { + self.inner.clone().into() + } + + /// Return the device key algorithm as a string. + #[wasm_bindgen(js_name = "toString")] + #[allow(clippy::inherent_to_string)] + pub fn to_string(&self) -> String { + self.inner.to_string() + } +} + +/// The basic key algorithm names in the specification. +#[wasm_bindgen] +pub enum DeviceKeyAlgorithmName { + /// The Ed25519 signature algorithm. + Ed25519, + + /// The Curve25519 ECDH algorithm. + Curve25519, + + /// The Curve25519 ECDH algorithm, but the key also contains + /// signatures. + SignedCurve25519, + + /// An unknown device key algorithm. + Unknown, +} + +impl From for DeviceKeyAlgorithmName { + fn from(value: ruma::DeviceKeyAlgorithm) -> Self { + use ruma::DeviceKeyAlgorithm::*; + + match value { + Ed25519 => Self::Ed25519, + Curve25519 => Self::Curve25519, + SignedCurve25519 => Self::SignedCurve25519, + _ => Self::Unknown, + } + } +} + /// A Matrix [room ID]. /// /// [room ID]: https://spec.matrix.org/v1.2/appendices/#room-ids-and-event-ids diff --git a/bindings/matrix-sdk-crypto-js/tests/identifiers.test.js b/bindings/matrix-sdk-crypto-js/tests/identifiers.test.js index 3b72da2ff..0609a9d9b 100644 --- a/bindings/matrix-sdk-crypto-js/tests/identifiers.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/identifiers.test.js @@ -1,4 +1,4 @@ -const { UserId, DeviceId, RoomId, ServerName } = require('../pkg/matrix_sdk_crypto_js'); +const { UserId, DeviceId, DeviceKeyId, DeviceKeyAlgorithm, DeviceKeyAlgorithmName, RoomId, ServerName } = require('../pkg/matrix_sdk_crypto_js'); describe(UserId.name, () => { test('cannot be invalid', () => { @@ -32,6 +32,52 @@ describe(DeviceId.name, () => { }) }); +describe(DeviceKeyId.name, () => { + for (const deviceKey of [ + { name: 'ed25519', + id: 'ed25519:foobar', + algorithmName: DeviceKeyAlgorithmName.Ed25519, + algorithm: 'ed25519', + deviceId: 'foobar' }, + + { name: 'curve25519', + id: 'curve25519:foobar', + algorithmName: DeviceKeyAlgorithmName.Curve25519, + algorithm: 'curve25519', + deviceId: 'foobar' }, + + { name: 'signed curve25519', + id: 'signed_curve25519:foobar', + algorithmName: DeviceKeyAlgorithmName.SignedCurve25519, + algorithm: 'signed_curve25519', + deviceId: 'foobar' }, + + { name: 'unknown', + id: 'hello:foobar', + algorithmName: DeviceKeyAlgorithmName.Unknown, + algorithm: 'hello', + deviceId: 'foobar' }, + ]) { + test(`${deviceKey.name} algorithm`, () => { + const dk = new DeviceKeyId(deviceKey.id); + + expect(dk.algorithm.name).toStrictEqual(deviceKey.algorithmName); + expect(dk.algorithm.toString()).toStrictEqual(deviceKey.algorithm); + expect(dk.deviceId.toString()).toStrictEqual(deviceKey.deviceId); + expect(dk.toString()).toStrictEqual(deviceKey.id); + }); + } +}); + +describe('DeviceKeyAlgorithmName', () => { + test('has the correct variants', () => { + expect(DeviceKeyAlgorithmName.Ed25519).toStrictEqual(0); + expect(DeviceKeyAlgorithmName.Curve25519).toStrictEqual(1); + expect(DeviceKeyAlgorithmName.SignedCurve25519).toStrictEqual(2); + expect(DeviceKeyAlgorithmName.Unknown).toStrictEqual(3); + }); +}); + describe(RoomId.name, () => { test('cannot be invalid', () => { expect(() => { new RoomId('!foo') }).toThrow();