Implement GPG key QR transfer
This commit is contained in:
@@ -3,7 +3,11 @@
|
||||
|
||||
//! Mechanical UniFFI exports for Apple presentation code.
|
||||
|
||||
use std::{error::Error, fmt, sync::Arc};
|
||||
use std::{
|
||||
error::Error,
|
||||
fmt,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use ironstorage::{
|
||||
config::ConfigError,
|
||||
@@ -27,6 +31,12 @@ use ironstorage::{
|
||||
MobileHomeErrorKind as StorageHomeErrorKind, MobileHomeFreshness as StorageHomeFreshness,
|
||||
MobileHomePhase as StorageHomePhase,
|
||||
},
|
||||
mobile_key_transfer::{
|
||||
MobileKeyTransferError as StorageKeyTransferError,
|
||||
MobileKeyTransferKey as StorageKeyTransferKey,
|
||||
MobileKeyTransferKind as StorageKeyTransferKind,
|
||||
MobileKeyTransferProgress as StorageKeyTransferProgress,
|
||||
},
|
||||
mobile_onboarding::{
|
||||
self, MobileOnboardingError as StorageOnboardingError,
|
||||
MobileOnboardingErrorKind as StorageOnboardingErrorKind,
|
||||
@@ -868,6 +878,213 @@ impl From<StorageAuthenticationState> for MobileAuthenticationState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, uniffi::Enum)]
|
||||
pub enum MobileKeyTransferKind {
|
||||
Public,
|
||||
Private,
|
||||
}
|
||||
|
||||
impl From<StorageKeyTransferKind> for MobileKeyTransferKind {
|
||||
fn from(kind: StorageKeyTransferKind) -> Self {
|
||||
match kind {
|
||||
StorageKeyTransferKind::Public => Self::Public,
|
||||
StorageKeyTransferKind::Private => Self::Private,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MobileKeyTransferKind> for StorageKeyTransferKind {
|
||||
fn from(kind: MobileKeyTransferKind) -> Self {
|
||||
match kind {
|
||||
MobileKeyTransferKind::Public => Self::Public,
|
||||
MobileKeyTransferKind::Private => Self::Private,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, uniffi::Record)]
|
||||
pub struct MobileKeyTransferKey {
|
||||
pub fingerprint: String,
|
||||
pub title: String,
|
||||
pub detail: String,
|
||||
pub kind: MobileKeyTransferKind,
|
||||
pub requires_passphrase: bool,
|
||||
}
|
||||
|
||||
impl From<&StorageKeyTransferKey> for MobileKeyTransferKey {
|
||||
fn from(key: &StorageKeyTransferKey) -> Self {
|
||||
Self {
|
||||
fingerprint: key.fingerprint().to_owned(),
|
||||
title: key.title().to_owned(),
|
||||
detail: key.detail().to_owned(),
|
||||
kind: key.kind().into(),
|
||||
requires_passphrase: key.requires_passphrase(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, uniffi::Record)]
|
||||
pub struct MobileKeyTransferFrame {
|
||||
pub sequence: u32,
|
||||
pub total: u32,
|
||||
pub width: u32,
|
||||
pub modules: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, uniffi::Record)]
|
||||
pub struct MobileKeyTransferExport {
|
||||
pub key: MobileKeyTransferKey,
|
||||
pub frames: Vec<MobileKeyTransferFrame>,
|
||||
}
|
||||
|
||||
#[derive(Clone, uniffi::Record)]
|
||||
pub struct MobileKeyTransferProgress {
|
||||
pub received: u32,
|
||||
pub total: u32,
|
||||
pub duplicate: bool,
|
||||
pub key: Option<MobileKeyTransferKey>,
|
||||
}
|
||||
|
||||
impl From<StorageKeyTransferProgress> for MobileKeyTransferProgress {
|
||||
fn from(progress: StorageKeyTransferProgress) -> Self {
|
||||
Self {
|
||||
received: u32::try_from(progress.received()).unwrap_or(u32::MAX),
|
||||
total: u32::try_from(progress.total()).unwrap_or(u32::MAX),
|
||||
duplicate: progress.duplicate(),
|
||||
key: progress.key().map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, uniffi::Record)]
|
||||
pub struct MobileKeyTransferOutcome {
|
||||
pub title: String,
|
||||
pub detail: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, uniffi::Error)]
|
||||
pub enum MobileKeyTransferFfiError {
|
||||
Failed { message: String },
|
||||
}
|
||||
|
||||
impl fmt::Display for MobileKeyTransferFfiError {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Failed { message } => formatter.write_str(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for MobileKeyTransferFfiError {}
|
||||
|
||||
impl From<StorageKeyTransferError> for MobileKeyTransferFfiError {
|
||||
fn from(error: StorageKeyTransferError) -> Self {
|
||||
Self::Failed {
|
||||
message: error.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct MobileKeyTransfer {
|
||||
service: ironstorage::mobile_key_transfer::MobileKeyTransferService,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl MobileKeyTransfer {
|
||||
pub fn keys(&self) -> Vec<MobileKeyTransferKey> {
|
||||
self.service.keys().iter().map(Into::into).collect()
|
||||
}
|
||||
|
||||
pub fn export(
|
||||
&self,
|
||||
fingerprint: String,
|
||||
kind: MobileKeyTransferKind,
|
||||
passphrase: Option<String>,
|
||||
) -> Result<MobileKeyTransferExport, MobileKeyTransferFfiError> {
|
||||
let exported = self.service.export(
|
||||
&fingerprint,
|
||||
kind.into(),
|
||||
passphrase.map(|value| ironstorage::repository::SecretBytes::new(value.into_bytes())),
|
||||
)?;
|
||||
let frames = exported
|
||||
.frames()
|
||||
.iter()
|
||||
.map(|frame| {
|
||||
let matrix = frame.matrix();
|
||||
let mut modules = Vec::with_capacity(matrix.width() * matrix.width());
|
||||
for y in 0..matrix.width() {
|
||||
for x in 0..matrix.width() {
|
||||
modules.push(u8::from(matrix.is_dark(x, y).unwrap_or(false)));
|
||||
}
|
||||
}
|
||||
MobileKeyTransferFrame {
|
||||
sequence: u32::try_from(frame.sequence()).unwrap_or(u32::MAX),
|
||||
total: u32::try_from(frame.total()).unwrap_or(u32::MAX),
|
||||
width: u32::try_from(matrix.width()).unwrap_or(u32::MAX),
|
||||
modules,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
Ok(MobileKeyTransferExport {
|
||||
key: exported.key().into(),
|
||||
frames,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn importer(&self) -> Arc<MobileKeyTransferImport> {
|
||||
Arc::new(MobileKeyTransferImport {
|
||||
importer: Mutex::new(self.service.importer()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct MobileKeyTransferImport {
|
||||
importer: Mutex<ironstorage::mobile_key_transfer::MobileKeyTransferImport>,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl MobileKeyTransferImport {
|
||||
pub fn add_frame(
|
||||
&self,
|
||||
payload: String,
|
||||
) -> Result<MobileKeyTransferProgress, MobileKeyTransferFfiError> {
|
||||
self.importer
|
||||
.lock()
|
||||
.map_err(|_| MobileKeyTransferFfiError::Failed {
|
||||
message: "the key-transfer session is unavailable".to_owned(),
|
||||
})?
|
||||
.add_frame(ironstorage::repository::SecretBytes::new(
|
||||
payload.into_bytes(),
|
||||
))
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn import(
|
||||
&self,
|
||||
passphrase: Option<String>,
|
||||
make_default: bool,
|
||||
) -> Result<MobileKeyTransferOutcome, MobileKeyTransferFfiError> {
|
||||
let outcome = self
|
||||
.importer
|
||||
.lock()
|
||||
.map_err(|_| MobileKeyTransferFfiError::Failed {
|
||||
message: "the key-transfer session is unavailable".to_owned(),
|
||||
})?
|
||||
.import(
|
||||
passphrase
|
||||
.map(|value| ironstorage::repository::SecretBytes::new(value.into_bytes())),
|
||||
make_default,
|
||||
)?;
|
||||
Ok(MobileKeyTransferOutcome {
|
||||
title: outcome.title().to_owned(),
|
||||
detail: outcome.detail().to_owned(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, uniffi::Error)]
|
||||
pub enum MobileAuthenticationFfiError {
|
||||
Failed {
|
||||
@@ -1388,6 +1605,13 @@ pub fn mobile_authentication() -> Result<Arc<MobileAuthentication>, MobileAuthen
|
||||
}))
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
pub fn mobile_key_transfer() -> Result<Arc<MobileKeyTransfer>, MobileKeyTransferFfiError> {
|
||||
Ok(Arc::new(MobileKeyTransfer {
|
||||
service: ironstorage::mobile_key_transfer::MobileKeyTransferService::load()?,
|
||||
}))
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
pub fn mobile_onboarding_operation(
|
||||
server_url: String,
|
||||
|
||||
Reference in New Issue
Block a user