use std::io::{Cursor, Read};
use byteorder::{BigEndian, ReadBytesExt};
use qrcode::QrCode;
use ruma::serde::Base64;
use vodozemac::Ed25519PublicKey;
use crate::{
error::{DecodingError, EncodingError},
utils::{HEADER, MAX_MODE, MIN_SECRET_LEN, VERSION, to_bytes, to_qr_code},
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum QrVerificationData {
Verification(VerificationData),
SelfVerification(SelfVerificationData),
SelfVerificationNoMasterKey(SelfVerificationNoMasterKey),
}
impl TryFrom<&[u8]> for QrVerificationData {
type Error = DecodingError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
Self::from_bytes(value)
}
}
impl TryFrom<Vec<u8>> for QrVerificationData {
type Error = DecodingError;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
Self::from_bytes(value)
}
}
impl QrVerificationData {
pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, DecodingError> {
Self::decode_bytes(bytes)
}
pub fn to_qr_code(&self) -> Result<QrCode, EncodingError> {
match self {
QrVerificationData::Verification(v) => v.to_qr_code(),
QrVerificationData::SelfVerification(v) => v.to_qr_code(),
QrVerificationData::SelfVerificationNoMasterKey(v) => v.to_qr_code(),
}
}
pub fn to_bytes(&self) -> Result<Vec<u8>, EncodingError> {
match self {
QrVerificationData::Verification(v) => v.to_bytes(),
QrVerificationData::SelfVerification(v) => v.to_bytes(),
QrVerificationData::SelfVerificationNoMasterKey(v) => v.to_bytes(),
}
}
fn decode_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, DecodingError> {
let mut decoded = Cursor::new(bytes);
let mut header = [0u8; 6];
let mut first_key = [0u8; 32];
let mut second_key = [0u8; 32];
decoded.read_exact(&mut header)?;
let version = decoded.read_u8()?;
let mode = decoded.read_u8()?;
if header != HEADER {
return Err(DecodingError::Header);
} else if version != VERSION {
return Err(DecodingError::Version(version));
} else if mode > MAX_MODE {
return Err(DecodingError::Mode(mode));
}
let flow_id_len = decoded.read_u16::<BigEndian>()?;
let mut flow_id = vec![0; flow_id_len.into()];
decoded.read_exact(&mut flow_id)?;
decoded.read_exact(&mut first_key)?;
decoded.read_exact(&mut second_key)?;
let mut shared_secret = Vec::new();
decoded.read_to_end(&mut shared_secret)?;
if shared_secret.len() < MIN_SECRET_LEN {
return Err(DecodingError::SharedSecret(shared_secret.len()));
}
let first_key = Ed25519PublicKey::from_slice(&first_key)?;
let second_key = Ed25519PublicKey::from_slice(&second_key)?;
QrVerificationData::new(mode, flow_id, first_key, second_key, shared_secret)
}
fn new(
mode: u8,
flow_id: Vec<u8>,
first_key: Ed25519PublicKey,
second_key: Ed25519PublicKey,
shared_secret: Vec<u8>,
) -> Result<Self, DecodingError> {
let flow_id = String::from_utf8(flow_id)?;
let shared_secret = Base64::new(shared_secret);
match mode {
VerificationData::QR_MODE => {
Ok(VerificationData::new(flow_id, first_key, second_key, shared_secret).into())
}
SelfVerificationData::QR_MODE => {
Ok(SelfVerificationData::new(flow_id, first_key, second_key, shared_secret).into())
}
SelfVerificationNoMasterKey::QR_MODE => {
Ok(SelfVerificationNoMasterKey::new(flow_id, first_key, second_key, shared_secret)
.into())
}
m => Err(DecodingError::Mode(m)),
}
}
pub fn flow_id(&self) -> &str {
match self {
QrVerificationData::Verification(v) => v.flow_id.as_str(),
QrVerificationData::SelfVerification(v) => &v.transaction_id,
QrVerificationData::SelfVerificationNoMasterKey(v) => &v.transaction_id,
}
}
pub fn first_key(&self) -> Ed25519PublicKey {
match self {
QrVerificationData::Verification(v) => v.first_master_key,
QrVerificationData::SelfVerification(v) => v.master_key,
QrVerificationData::SelfVerificationNoMasterKey(v) => v.device_key,
}
}
pub fn second_key(&self) -> Ed25519PublicKey {
match self {
QrVerificationData::Verification(v) => v.second_master_key,
QrVerificationData::SelfVerification(v) => v.device_key,
QrVerificationData::SelfVerificationNoMasterKey(v) => v.master_key,
}
}
pub fn secret(&self) -> &Base64 {
match self {
QrVerificationData::Verification(v) => &v.shared_secret,
QrVerificationData::SelfVerification(v) => &v.shared_secret,
QrVerificationData::SelfVerificationNoMasterKey(v) => &v.shared_secret,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VerificationData {
flow_id: String,
first_master_key: Ed25519PublicKey,
second_master_key: Ed25519PublicKey,
shared_secret: Base64,
}
impl VerificationData {
const QR_MODE: u8 = 0x00;
pub fn new(
flow_id: String,
first_master_key: Ed25519PublicKey,
second_master_key: Ed25519PublicKey,
shared_secret: Base64,
) -> Self {
Self { flow_id, first_master_key, second_master_key, shared_secret }
}
pub fn to_bytes(&self) -> Result<Vec<u8>, EncodingError> {
to_bytes(
Self::QR_MODE,
self.flow_id.as_str(),
self.first_master_key,
self.second_master_key,
&self.shared_secret,
)
}
pub fn to_qr_code(&self) -> Result<QrCode, EncodingError> {
to_qr_code(
Self::QR_MODE,
self.flow_id.as_str(),
self.first_master_key,
self.second_master_key,
&self.shared_secret,
)
}
}
impl From<VerificationData> for QrVerificationData {
fn from(data: VerificationData) -> Self {
Self::Verification(data)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SelfVerificationData {
transaction_id: String,
master_key: Ed25519PublicKey,
device_key: Ed25519PublicKey,
shared_secret: Base64,
}
impl SelfVerificationData {
const QR_MODE: u8 = 0x01;
pub fn new(
transaction_id: String,
master_key: Ed25519PublicKey,
device_key: Ed25519PublicKey,
shared_secret: Base64,
) -> Self {
Self { transaction_id, master_key, device_key, shared_secret }
}
pub fn to_bytes(&self) -> Result<Vec<u8>, EncodingError> {
to_bytes(
Self::QR_MODE,
&self.transaction_id,
self.master_key,
self.device_key,
&self.shared_secret,
)
}
pub fn to_qr_code(&self) -> Result<QrCode, EncodingError> {
to_qr_code(
Self::QR_MODE,
&self.transaction_id,
self.master_key,
self.device_key,
&self.shared_secret,
)
}
}
impl From<SelfVerificationData> for QrVerificationData {
fn from(data: SelfVerificationData) -> Self {
Self::SelfVerification(data)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SelfVerificationNoMasterKey {
transaction_id: String,
device_key: Ed25519PublicKey,
master_key: Ed25519PublicKey,
shared_secret: Base64,
}
impl SelfVerificationNoMasterKey {
const QR_MODE: u8 = 0x02;
pub fn new(
transaction_id: String,
device_key: Ed25519PublicKey,
master_key: Ed25519PublicKey,
shared_secret: Base64,
) -> Self {
Self { transaction_id, device_key, master_key, shared_secret }
}
pub fn to_bytes(&self) -> Result<Vec<u8>, EncodingError> {
to_bytes(
Self::QR_MODE,
&self.transaction_id,
self.device_key,
self.master_key,
&self.shared_secret,
)
}
pub fn to_qr_code(&self) -> Result<QrCode, EncodingError> {
to_qr_code(
Self::QR_MODE,
&self.transaction_id,
self.device_key,
self.master_key,
&self.shared_secret,
)
}
}
impl From<SelfVerificationNoMasterKey> for QrVerificationData {
fn from(data: SelfVerificationNoMasterKey) -> Self {
Self::SelfVerificationNoMasterKey(data)
}
}