Signed assertions

This commit is contained in:
jml 2026-02-16 04:46:53 +00:00
parent fae9b47fae
commit 3df4aa7167
2 changed files with 42 additions and 2 deletions

View File

@ -46,6 +46,7 @@ getrandom = "0.2"
metrics = "0.23"
metrics-exporter-prometheus = "0.15"
dashmap = "6.0"
ed25519-dalek = { version = "2.1", features = ["rand_core"] }
[dev-dependencies]
tempfile = "3"

View File

@ -5,8 +5,10 @@
use axum::{extract::{Path, State}, http::StatusCode, Json};
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_storage::{key_codec, KVStore};
@ -16,6 +18,40 @@ use crate::{
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
// ============================================================================
@ -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");
// 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
let payload = serialize_assertion(&assertion)