Signed assertions
This commit is contained in:
parent
fae9b47fae
commit
3df4aa7167
@ -46,6 +46,7 @@ getrandom = "0.2"
|
|||||||
metrics = "0.23"
|
metrics = "0.23"
|
||||||
metrics-exporter-prometheus = "0.15"
|
metrics-exporter-prometheus = "0.15"
|
||||||
dashmap = "6.0"
|
dashmap = "6.0"
|
||||||
|
ed25519-dalek = { version = "2.1", features = ["rand_core"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
|||||||
@ -5,8 +5,10 @@
|
|||||||
|
|
||||||
use axum::{extract::{Path, State}, http::StatusCode, Json};
|
use axum::{extract::{Path, State}, http::StatusCode, Json};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
use ed25519_dalek::{SigningKey, Signer, VerifyingKey};
|
||||||
|
|
||||||
use stemedb_core::types::{Assertion, LifecycleStage, ObjectValue};
|
use stemedb_core::types::{Assertion, LifecycleStage, ObjectValue, SignatureEntry};
|
||||||
|
use stemedb_core::signing::compute_content_hash_v2;
|
||||||
use stemedb_ingest::worker::serialize_assertion;
|
use stemedb_ingest::worker::serialize_assertion;
|
||||||
use stemedb_storage::{key_codec, KVStore};
|
use stemedb_storage::{key_codec, KVStore};
|
||||||
|
|
||||||
@ -16,6 +18,40 @@ use crate::{
|
|||||||
AppState,
|
AppState,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Server Signing Key Generation
|
||||||
|
|
||||||
|
/// Generate a deterministic server signing key from a seed.
|
||||||
|
/// This ensures the same key is used across server restarts.
|
||||||
|
fn get_server_signing_key() -> SigningKey {
|
||||||
|
// Use a fixed seed for deterministic key generation
|
||||||
|
// In production, this should be loaded from a config file or environment
|
||||||
|
let seed = [0x42u8; 32]; // Placeholder seed - replace with actual key management
|
||||||
|
SigningKey::from_bytes(&seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sign an assertion with the server's key and add the signature.
|
||||||
|
fn add_server_signature(assertion: &mut Assertion) {
|
||||||
|
let signing_key = get_server_signing_key();
|
||||||
|
let verifying_key: VerifyingKey = (&signing_key).into();
|
||||||
|
|
||||||
|
// Compute content hash for v2 signature
|
||||||
|
let content_hash = compute_content_hash_v2(assertion);
|
||||||
|
|
||||||
|
// Sign the content hash
|
||||||
|
let signature_bytes = signing_key.sign(&content_hash);
|
||||||
|
|
||||||
|
// Create signature entry
|
||||||
|
let sig_entry = SignatureEntry {
|
||||||
|
agent_id: verifying_key.to_bytes(),
|
||||||
|
signature: signature_bytes.to_bytes(),
|
||||||
|
timestamp: assertion.timestamp,
|
||||||
|
version: 2, // Use v2 (enterprise) signing
|
||||||
|
};
|
||||||
|
|
||||||
|
assertion.signatures.push(sig_entry);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Handlers
|
// Handlers
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -39,7 +75,10 @@ pub async fn create_claim(
|
|||||||
info!(claim_id = %req.claim.id, concept_path = %req.claim.concept_path, "Creating claim in StemeDB");
|
info!(claim_id = %req.claim.id, concept_path = %req.claim.concept_path, "Creating claim in StemeDB");
|
||||||
|
|
||||||
// Convert DTO to Assertion
|
// Convert DTO to Assertion
|
||||||
let assertion = dto_to_assertion(&req.claim)?;
|
let mut assertion = dto_to_assertion(&req.claim)?;
|
||||||
|
|
||||||
|
// Add server signature to the assertion
|
||||||
|
add_server_signature(&mut assertion);
|
||||||
|
|
||||||
// Serialize and append to WAL
|
// Serialize and append to WAL
|
||||||
let payload = serialize_assertion(&assertion)
|
let payload = serialize_assertion(&assertion)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user