feat(wasm): add generate_device_keypair + get_field_history bindings
generate_device_keypair returns an ed25519 keypair as JSON with hex pubkey and base64 private key. get_field_history extracts tracked field history from a decrypted item for the popup's history view. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -162,6 +162,12 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.8.3"
|
||||
@@ -1557,8 +1563,12 @@ dependencies = [
|
||||
name = "relicario-wasm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"ed25519-dalek",
|
||||
"getrandom 0.2.17",
|
||||
"hex",
|
||||
"image",
|
||||
"rand",
|
||||
"relicario-core",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
|
||||
@@ -15,6 +15,10 @@ serde_json = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
zeroize = "1"
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
ed25519-dalek = { version = "2", features = ["rand_core"] }
|
||||
base64 = "0.22"
|
||||
hex = "0.4"
|
||||
rand = "0.8"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3"
|
||||
|
||||
@@ -196,6 +196,64 @@ pub fn rate_passphrase(p: &str) -> Result<JsValue, JsError> {
|
||||
}))
|
||||
}
|
||||
|
||||
use ed25519_dalek::SigningKey;
|
||||
use base64::Engine;
|
||||
|
||||
/// Generate an ed25519 keypair for device registration.
|
||||
/// Returns JSON: { "public_key_hex": "...", "private_key_base64": "..." }
|
||||
#[wasm_bindgen]
|
||||
pub fn generate_device_keypair() -> Result<JsValue, JsError> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let signing_key = SigningKey::generate(&mut rng);
|
||||
let verifying_key = signing_key.verifying_key();
|
||||
|
||||
let public_hex = hex::encode(verifying_key.as_bytes());
|
||||
let private_b64 = base64::engine::general_purpose::STANDARD.encode(signing_key.as_bytes());
|
||||
|
||||
js_value_for(&serde_json::json!({
|
||||
"public_key_hex": public_hex,
|
||||
"private_key_base64": private_b64,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Extract field history from a decrypted item JSON.
|
||||
/// Returns JSON array of { field_id, field_name, current_value, entries: [{ value, changed_at }] }
|
||||
#[wasm_bindgen]
|
||||
pub fn get_field_history(item_json: &str) -> Result<JsValue, JsError> {
|
||||
let item: Item = serde_json::from_str(item_json)
|
||||
.map_err(|e| JsError::new(&format!("item json: {e}")))?;
|
||||
|
||||
let mut results = Vec::new();
|
||||
|
||||
// Only section fields are tracked in field_history (set_field_value operates on sections).
|
||||
for section in &item.sections {
|
||||
for field in §ion.fields {
|
||||
if field.value.is_history_tracked() {
|
||||
if let Some(entries) = item.field_history.get(&field.id) {
|
||||
if !entries.is_empty() {
|
||||
let current = match &field.value {
|
||||
relicario_core::FieldValue::Password(v) => v.as_str().to_owned(),
|
||||
relicario_core::FieldValue::Concealed(v) => v.as_str().to_owned(),
|
||||
_ => String::new(),
|
||||
};
|
||||
results.push(serde_json::json!({
|
||||
"field_id": field.id.as_str(),
|
||||
"field_name": &field.label,
|
||||
"current_value": current,
|
||||
"entries": entries.iter().map(|e| serde_json::json!({
|
||||
"value": e.value.as_str(),
|
||||
"changed_at": e.replaced_at,
|
||||
})).collect::<Vec<_>>(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
js_value_for(&results)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn extract_image_secret(image_bytes: &[u8]) -> Result<Vec<u8>, JsError> {
|
||||
let s = imgsecret::extract(image_bytes).map_err(|e| JsError::new(&e.to_string()))?;
|
||||
|
||||
Reference in New Issue
Block a user