use ed25519_dalek::{SigningKey, VerifyingKey};
use rand_core::{OsRng, RngCore};
use serde::{Deserialize, Serialize};
use crate::{codec, identity::UserId};
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct DeviceId(#[serde(with = "serde_bytes")] pub Vec<u8>);
impl DeviceId {
pub fn from_pubkey(pk: &VerifyingKey) -> Self {
DeviceId(codec::sha256(pk.as_bytes()).to_vec())
}
pub fn as_hex(&self) -> String {
hex::encode(&self.0)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceInfo {
pub device_id: DeviceId,
pub user_id: UserId,
pub label: String, pub created_at_ms: u64,
pub last_seen_ms: u64,
pub revoked: bool,
}
pub struct LocalDevice {
pub device_id: DeviceId,
pub user_id: UserId,
pub label: String,
pub(crate) signing: SigningKey,
pub created_at_ms: u64,
}
impl std::fmt::Debug for LocalDevice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LocalDevice")
.field("device_id", &self.device_id.as_hex())
.field("user_id", &self.user_id.as_hex())
.field("label", &self.label)
.finish()
}
}
impl LocalDevice {
pub fn generate(user_id: UserId, label: String, now_ms: u64) -> Self {
let mut seed = [0u8; 32];
OsRng.fill_bytes(&mut seed);
let signing = SigningKey::from_bytes(&seed);
let device_id = DeviceId::from_pubkey(&signing.verifying_key());
LocalDevice {
device_id,
user_id,
label,
signing,
created_at_ms: now_ms,
}
}
pub fn public_key(&self) -> VerifyingKey {
self.signing.verifying_key()
}
pub fn info(&self, last_seen_ms: u64) -> DeviceInfo {
DeviceInfo {
device_id: self.device_id.clone(),
user_id: self.user_id.clone(),
label: self.label.clone(),
created_at_ms: self.created_at_ms,
last_seen_ms,
revoked: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LinkingTicket {
pub v: u8,
pub user_id: UserId,
#[serde(with = "serde_bytes")]
pub user_pubkey: Vec<u8>, pub new_device_id: DeviceId,
#[serde(with = "serde_bytes")]
pub device_binding_sig: Vec<u8>, #[serde(with = "serde_bytes")]
pub device_group_welcome: Vec<u8>, #[serde(with = "serde_bytes")]
pub catchup_snapshot: Vec<u8>, }