From 1e01d7e34483ca93c8cf8d62e755cb8965c94d64 Mon Sep 17 00:00:00 2001 From: lashman Date: Tue, 28 Apr 2026 22:27:22 +0300 Subject: [PATCH] ap signing keys --- cruciverb-server/src/activitypub/keys.rs | 51 ++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 cruciverb-server/src/activitypub/keys.rs diff --git a/cruciverb-server/src/activitypub/keys.rs b/cruciverb-server/src/activitypub/keys.rs new file mode 100644 index 0000000..b2537b9 --- /dev/null +++ b/cruciverb-server/src/activitypub/keys.rs @@ -0,0 +1,51 @@ +use rsa::{RsaPrivateKey, RsaPublicKey}; +use rsa::pkcs1::{EncodeRsaPrivateKey, EncodeRsaPublicKey, DecodeRsaPrivateKey, DecodeRsaPublicKey, LineEnding}; +use rusqlite::Connection; + +pub struct ApKeys { + pub private_key: RsaPrivateKey, + pub public_key_pem: String, +} + +pub fn load_or_generate(db: &Connection) -> ApKeys { + // try loading from DB + if let Ok((pub_pem, priv_pem)) = db.query_row( + "SELECT public_pem, private_pem FROM ap_keys WHERE id = 1", + [], + |row| Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?)), + ) { + let private_key = RsaPrivateKey::from_pkcs1_pem(&priv_pem) + .expect("failed to parse stored RSA private key"); + let _ = RsaPublicKey::from_pkcs1_pem(&pub_pem) + .expect("failed to parse stored RSA public key"); + return ApKeys { + private_key, + public_key_pem: pub_pem, + }; + } + + // generate new 2048-bit key pair + tracing::info!("generating RSA-2048 key pair for ActivityPub..."); + let mut rng = rsa::rand_core::OsRng; + let private_key = RsaPrivateKey::new(&mut rng, 2048) + .expect("failed to generate RSA key"); + let public_key = RsaPublicKey::from(&private_key); + + let pub_pem = public_key.to_pkcs1_pem(LineEnding::LF) + .expect("failed to encode public key"); + let priv_pem = private_key.to_pkcs1_pem(LineEnding::LF) + .expect("failed to encode private key"); + + let now = chrono::Utc::now().to_rfc3339(); + db.execute( + "INSERT INTO ap_keys (id, public_pem, private_pem, created_at) VALUES (1, ?1, ?2, ?3)", + rusqlite::params![pub_pem, priv_pem.as_str(), now], + ).expect("failed to store RSA keys"); + + tracing::info!("RSA key pair generated and stored"); + + ApKeys { + private_key, + public_key_pem: pub_pem, + } +}