Files
upstream-mirror 9ad64ec987
Some checks failed
integration tests / run-integration-tests (windows-latest) (push) Has been cancelled
Test Rust / test (push) Has been cancelled
test plugins e2e (mobile) / ios (push) Has been cancelled
test plugins e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test plugins e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
integration tests / run-integration-tests (macos-latest) (push) Has been cancelled
version or publish / version-or-publish (push) Failing after 0s
integration tests / run-integration-tests (ubuntu-22.04) (push) Failing after 0s
Lint JavaScript / eslint (push) Failing after 0s
Sync / sync-to-mirrors (push) Failing after 0s
test plugins e2e (mobile) / android (push) Failing after 0s
test plugins e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
Test Rust / changes (push) Failing after 0s
Lint Rust / changes (push) Failing after 0s
Lint Rust / clippy (push) Has been skipped
Audit Rust / audit-rust (push) Failing after 1s
Audit JavaScript / audit-js (push) Failing after 1s
snapshot of https://github.com/tauri-apps/plugins-workspace.git (v2, 2026-09-23; blobs > 131072B omitted)
2026-09-23 17:17:10 +05:00

104 lines
3.7 KiB
Rust

// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
//! Types to load, modify and persist an [IOTA Stronghold](https://github.com/iotaledger/stronghold.rs)
//! snapshot file.
use std::{convert::TryFrom, ops::Deref, path::Path};
use iota_stronghold::{KeyProvider, SnapshotPath};
use serde::{Serialize, Serializer};
use zeroize::Zeroizing;
/// Alias for a [`std::result::Result`] with the error type [`Error`].
pub type Result<T> = std::result::Result<T, Error>;
/// Errors returned by the stronghold plugin.
///
/// Serialized as the error message string when returned to the frontend.
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// No stronghold was initialized for the given snapshot path.
#[error("stronghold not initialized")]
StrongholdNotInitialized,
/// An error from the underlying Stronghold client, e.g. when loading a snapshot
/// with the wrong password or when addressing a client that does not exist.
#[error(transparent)]
Stronghold(#[from] iota_stronghold::ClientError),
/// An error from the Stronghold secure memory implementation, e.g. when the
/// password hash is not a key size Stronghold accepts.
#[error(transparent)]
Memory(#[from] iota_stronghold::MemoryError),
/// A Stronghold procedure (key generation, key derivation, signing, ...) failed.
#[error(transparent)]
Procedure(#[from] iota_stronghold::procedures::ProcedureError),
}
impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.to_string().as_str())
}
}
/// A Stronghold instance bound to a snapshot file and to the key it is encrypted with.
///
/// Dereferences to the underlying [`iota_stronghold::Stronghold`], so all of its client
/// and vault operations are available on this type.
pub struct Stronghold {
inner: iota_stronghold::Stronghold,
path: SnapshotPath,
keyprovider: KeyProvider,
}
impl Stronghold {
/// Creates a Stronghold instance for the snapshot file at `path`, encrypted with
/// `password` as the key.
///
/// When the file already exists its snapshot is loaded, which requires `password` to
/// be the key it was encrypted with. Otherwise an empty instance is created and
/// nothing is written to disk until [`Self::save`] is called.
///
/// # Errors
///
/// Returns [`Error::Memory`] when `password` is not a key size Stronghold accepts
/// (it must be 32 bytes long) and [`Error::Stronghold`] when an existing snapshot
/// cannot be loaded with it.
pub fn new<P: AsRef<Path>>(path: P, password: Vec<u8>) -> Result<Self> {
let path = SnapshotPath::from_path(path);
let stronghold = iota_stronghold::Stronghold::default();
let keyprovider = KeyProvider::try_from(Zeroizing::new(password))?;
if path.exists() {
stronghold.load_snapshot(&keyprovider, &path)?;
}
Ok(Self {
inner: stronghold,
path,
keyprovider,
})
}
/// Writes the state of all clients to the snapshot file, encrypted with the key
/// this instance was created with.
pub fn save(&self) -> Result<()> {
self.inner
.commit_with_keyprovider(&self.path, &self.keyprovider)?;
Ok(())
}
/// Returns a reference to the underlying [`iota_stronghold::Stronghold`] instance.
pub fn inner(&self) -> &iota_stronghold::Stronghold {
&self.inner
}
}
impl Deref for Stronghold {
type Target = iota_stronghold::Stronghold;
fn deref(&self) -> &Self::Target {
&self.inner
}
}