tuwunel_service/oauth/server/
signing_key.rs1use ring::{
2 rand::SystemRandom,
3 signature::{self, EcdsaKeyPair},
4};
5use serde::{Deserialize, Serialize};
6use tuwunel_core::{Result, at, err, info, utils};
7use tuwunel_database::{Cbor, Deserialized};
8
9use super::Data;
10
11#[derive(Deserialize, Serialize)]
12pub(super) struct SigningKey {
13 pub(super) key_id: String,
14 pub(super) key_der: Vec<u8>,
15}
16
17const SIGNING_KEY_DB_KEY: &str = "oidc_signing_key";
18
19pub(super) fn init_signing_key(db: &Data) -> Result<SigningKey> {
20 if let Ok(signing_key_data) = db
21 .oidc_signingkey
22 .get_blocking(SIGNING_KEY_DB_KEY)
23 .and_then(|val| val.deserialized::<Cbor<SigningKey>>())
24 .map(at!(0))
25 {
26 info!(
27 key_id = ?signing_key_data.key_id,
28 "Loaded existing OIDC signing key",
29 );
30
31 return Ok(signing_key_data);
32 }
33
34 let signing_key_data = generate_signing_key()?;
35
36 db.oidc_signingkey
37 .raw_put(SIGNING_KEY_DB_KEY, Cbor(&signing_key_data));
38
39 info!(
40 key_id = ?signing_key_data.key_id,
41 "Generated new OIDC signing key",
42 );
43
44 Ok(signing_key_data)
45}
46
47fn generate_signing_key() -> Result<SigningKey> {
48 let rng = SystemRandom::new();
49 let alg = &signature::ECDSA_P256_SHA256_FIXED_SIGNING;
50 let key_id = utils::random_string(16);
51 let pkcs8 = EcdsaKeyPair::generate_pkcs8(alg, &rng)
52 .map_err(|e| err!(error!("Failed to generate ECDSA key: {e}")))?;
53
54 Ok(SigningKey { key_der: pkcs8.as_ref().to_vec(), key_id })
55}