Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
96710ae
refactor: KMS for wallet - traits, WIP
lklimek Jun 11, 2025
dc3feb6
WIP: KeyStorage -> Kms, remove privkeys from identity, not building
lklimek Jun 11, 2025
2cc116b
Merge remote-tracking branch 'origin/v0.9-dev' into refactor/kms
lklimek Jun 18, 2025
b927cc7
chore: revert all changes
lklimek Jun 18, 2025
2168b1b
chore: dash-platform-wallet/kms
lklimek Jun 18, 2025
fca7324
Merge remote-tracking branch 'origin/v0.9-dev' into refactor/kms
lklimek Jun 23, 2025
383e37a
chore: kms wip
lklimek Jun 25, 2025
5d80af6
Merge remote-tracking branch 'origin/v0.9-dev' into refactor/kms
lklimek Jun 27, 2025
048e157
wip: dash-platform-wallet KMS compiling, but not saving yet
lklimek Jul 4, 2025
0ff27c3
chore: move generic kms to generic mod
lklimek Jul 4, 2025
e6b53a5
chore: impl serde for KeyHandle
lklimek Jul 4, 2025
e91aca3
chore: compiling but IdentityPublicKey deserialization fails
lklimek Jul 4, 2025
00b4218
chore: cargo.toml
lklimek Jul 7, 2025
8411453
chore: generic kms tests
lklimek Jul 8, 2025
b3402c6
chore: wip
lklimek Jul 8, 2025
02668cc
chore: fixed tests
lklimek Jul 8, 2025
049bbd7
chore: improve tests
lklimek Jul 9, 2025
ed14158
chore: add user password to store, wip
lklimek Jul 9, 2025
ace448f
chore: multi-user
lklimek Jul 9, 2025
0bd1284
chore: multi-user support
lklimek Jul 9, 2025
1223a4a
chore: pubkey with type, signature verification
lklimek Jul 9, 2025
29906b9
chore: small refactor
lklimek Jul 10, 2025
883b6a8
chore: wallet, WIP
lklimek Jul 10, 2025
2302890
chore: key derive WIP
lklimek Jul 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
280 changes: 227 additions & 53 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ qrcode = "0.14.1"
nix = { version = "0.30.1", features = ["signal"] }
eframe = { version = "0.31.1", features = ["persistence"] }
base64 = "0.22.1"
dash-sdk = { git = "https://github.com/dashpay/platform", rev = "5b8b29df2d0f58f52ae75b8d0672378df4b9e154" }
dash-sdk = { git = "https://github.com/dashpay/platform", rev = "bab21b3b2b55439389d4bfeb9dd87fcfb805c21b" }
thiserror = "2.0.12"
serde = "1.0.219"
serde_json = "1.0.140"
Expand Down Expand Up @@ -55,6 +55,7 @@ regex = "1.11.1"
humantime = "2.2.0"
which = { version = "7.0.3" }
tz-rs = { version = "0.7.0" }
dash-platform-wallet = { path = "dash-platform-wallet" }

[target.'cfg(not(target_os = "windows"))'.dependencies]
zmq = "0.10.0"
Expand All @@ -70,3 +71,6 @@ raw-cpuid = "11.5.0"

tempfile = { version = "3.20.0" }
egui_kittest = { version = "0.31.1", features = ["eframe"] }

[workspace]
members = [".", "dash-platform-wallet"]
24 changes: 24 additions & 0 deletions dash-platform-wallet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "dash-platform-wallet"
version = "0.1.0"
edition = "2024"

[dependencies]
dash-sdk = { git = "https://github.com/dashpay/platform", rev = "bab21b3b2b55439389d4bfeb9dd87fcfb805c21b" }
zeroize = { version = "1.8.1" }
thiserror = "2.0.12"
serde = "1.0.219"
serde_json = "1.0.140"
serde_with = { version = "3.14.0", features = ["hex"] }
rand = "0.9.1"
rand_chacha = "0.9.0"
argon2 = { version = "0.5.3", features = ["zeroize"] }
bitflags = "2.9.1"
bip39 = { version = "2.1.0", features = ["all-languages", "rand"] }
aes-gcm = { version = "0.10.3", features = ["zeroize", "heapless"] }
sha2 = "0.10.9"
hex = "0.4.3"
region = { version = "3.0.2" }
tracing = { version = "0.1.41" }
[dev-dependencies]
tempfile = "3.5.0"
Empty file.
164 changes: 164 additions & 0 deletions dash-platform-wallet/src/kms/file_store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use core::{cmp::Ord, fmt::Debug, prelude::v1::derive};
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeMap,
io::Write,
ops::Deref,
path::{Path, PathBuf},
sync::{Arc, RwLock},
};

use super::KVStore;

/// JSON storage for Key Management Service (KMS).
///
/// This module provides a JSON-based storage implementation for managing cryptographic keys
/// and related operations in a Key Management Service (KMS).
///
/// It encrypts values before storing them and decrypts them when retrieving.
///
/// Keys are stored in plaintext.
///
/// Data is base64 encoded before storing and decoded after retrieving.
///
///
/// ## Cloning
///
/// The `JsonStore` is designed to be cloneable, allowing multiple instances to share the same underlying data.
#[derive(Clone)]
pub struct FileStore<K: Ord, V> {
// where
// K: Clone + std::fmt::Debug + Serialize + for<'de> Deserialize<'de> + Ord,
// V: Clone + Serialize + for<'de> Deserialize<'de>,
path: PathBuf,
db: Arc<RwLock<Database<K, V>>>,
}

impl<K: Ord, V> Debug for FileStore<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("JsonStore")
.field("path", &self.path)
.finish()
}
}

#[derive(serde::Serialize, serde::Deserialize)]
struct Database<K: Ord, V> {
records: BTreeMap<K, V>,
}

#[derive(Debug, thiserror::Error)]
pub enum JsonStoreError {
#[error("I/O error: {0}")]
IoError(String),
#[error("JSON serialization/deserialization error: {0}")]
JsonError(#[from] serde_json::Error),
}

impl From<std::io::Error> for JsonStoreError {
fn from(err: std::io::Error) -> Self {
JsonStoreError::IoError(err.to_string())
}
}

impl<K, V> KVStore<K, V> for FileStore<K, V>
where
K: Clone + std::fmt::Debug + Serialize + for<'de> Deserialize<'de> + Ord,
V: Clone + Serialize + for<'de> Deserialize<'de>,
{
type Error = JsonStoreError;

fn get(&self, key: &K) -> Result<Option<V>, Self::Error> {
let db = self.db.read().expect("Failed to read from JSON store");
let record = db.records.get(key).cloned();
Ok(record)
}

fn set(&mut self, key: K, value: V) -> Result<(), Self::Error> {
let mut db = self.db.write().unwrap();
db.records.insert(key, value);
self.save(db.deref())?;
Ok(())
}

fn delete(&mut self, key: &K) -> Result<bool, Self::Error> {
let mut db = self.db.write().unwrap();
let removed = db.records.remove(key).is_some();
if removed {
self.save(db.deref())?;
}
Ok(removed)
}

fn keys(&self) -> Result<Vec<K>, Self::Error> {
let db = self.db.read().expect("Failed to read from JSON store");
Ok(db.records.keys().cloned().collect())
}

fn contains_key(&self, key: &K) -> Result<bool, Self::Error> {
let db = self.db.read().expect("Failed to read from JSON store");
Ok(db.records.contains_key(key))
}

fn clear(&mut self) -> Result<(), Self::Error> {
let mut db = self.db.write().unwrap();
db.records.clear();
self.save(db.deref())?;
Ok(())
}
}

impl<K, V> FileStore<K, V>
where
K: Clone + std::fmt::Debug + Serialize + for<'de> Deserialize<'de> + Ord,
V: Clone + Serialize + for<'de> Deserialize<'de>,
{
/// Creates a new instance of `JsonStore`.
pub fn new(path: &Path) -> Result<Self, JsonStoreError> {
let me = Self {
path: path.to_path_buf(),
db: Arc::new(RwLock::new(Database {
records: BTreeMap::new(),
})),
};
if path.exists() {
me.load()?;
} else {
// Create the file if it does not exist. We do this here to fail early if the file cannot be created.
let db = me.db.read().unwrap();
me.save(db.deref())?;
}

Ok(me)
}

/// Load database from the JSON store.
fn load(&self) -> Result<(), JsonStoreError> {
let file = std::fs::OpenOptions::new()
.read(true)
.write(false)
.open(&self.path)?;

let database: Database<K, V> = match serde_json::from_reader(&file) {
Ok(db) => db,
Err(e) => return Err(e.into()),
};

self.db.write().unwrap().records = database.records;

Ok(())
}

/// Save current database to the JSON store.
fn save(&self, db: &Database<K, V>) -> Result<(), JsonStoreError> {
let json = serde_json::to_vec_pretty(db)?;

let mut file = std::fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(&self.path)?;
file.write_all(&json)?;
Ok(())
}
}
1 change: 1 addition & 0 deletions dash-platform-wallet/src/kms/generic/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading