tuwunel_service/server_keys/
keypair.rs1use std::sync::Arc;
7
8use ruma::{api::federation::discovery::VerifyKey, serde::Base64, signatures::Ed25519KeyPair};
9use tuwunel_core::{Result, debug, debug_info, err, error, utils, utils::string_from_bytes};
10use tuwunel_database::Database;
11
12use super::VerifyKeys;
13
14pub(super) fn init(db: &Arc<Database>) -> Result<(Box<Ed25519KeyPair>, VerifyKeys)> {
19 let keypair = load(db).inspect_err(|_e| {
20 error!("Keypair invalid. Deleting...");
21 remove(db);
22 })?;
23
24 let verify_key = VerifyKey {
25 key: Base64::new(keypair.public_key().to_vec()),
26 };
27
28 let id = format!("ed25519:{}", keypair.version());
29 let verify_keys: VerifyKeys = [(id.try_into()?, verify_key)].into();
30
31 Ok((keypair, verify_keys))
32}
33
34fn load(db: &Arc<Database>) -> Result<Box<Ed25519KeyPair>> {
35 let (version, key) = db["global"]
36 .get_blocking(b"keypair")
37 .map(|ref val| {
38 let mut elems = val.split(|&b| b == b'\xFF');
40 let vlen = elems.next().expect("invalid keypair entry").len();
41 let ver = string_from_bytes(&val[..vlen]).expect("invalid keypair version");
42 let der = val[vlen.saturating_add(1)..].to_vec();
43 debug!("Found existing Ed25519 keypair: {ver:?}");
44 (ver, der)
45 })
46 .or_else(|e| {
47 assert!(e.is_not_found(), "unexpected error fetching keypair");
48 create(db)
49 })?;
50
51 let key = Ed25519KeyPair::from_der(&key, version)
52 .map_err(|e| err!("Failed to load ed25519 keypair from der: {e:?}"))?;
53
54 Ok(Box::new(key))
55}
56
57fn create(db: &Arc<Database>) -> Result<(String, Vec<u8>)> {
58 let keypair = Ed25519KeyPair::generate();
59
60 let id = utils::rand::string(8);
61 debug_info!("Generated new Ed25519 keypair: {id:?}");
62
63 let value: (String, Vec<u8>) = (id, keypair.to_vec());
64 db["global"].raw_put(b"keypair", &value);
65
66 Ok(value)
67}
68
69#[inline]
70fn remove(db: &Arc<Database>) {
71 let global = &db["global"];
72 global.remove(b"keypair");
73}