1use crate::{DntContext, DntKeyError, DntResult, KeyId};
14use std::collections::HashMap;
15use std::fmt;
16use zeroize::Zeroize;
17
18#[derive(Clone, PartialEq, Eq)]
20pub struct SecretKey([u8; 32]);
21
22impl SecretKey {
23 pub fn new(bytes: [u8; 32]) -> Self {
25 Self(bytes)
26 }
27
28 pub fn from_slice(bytes: &[u8]) -> Result<Self, DntKeyError> {
30 if bytes.len() != 32 {
31 return Err(DntKeyError::InvalidKey);
32 }
33 let mut key = [0u8; 32];
34 key.copy_from_slice(bytes);
35 Ok(Self(key))
36 }
37
38 pub fn expose_key(&self) -> &[u8; 32] {
40 &self.0
41 }
42}
43
44impl fmt::Debug for SecretKey {
45 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
46 formatter.write_str("SecretKey(REDACTED)")
47 }
48}
49
50impl Drop for SecretKey {
51 fn drop(&mut self) {
52 self.0.zeroize();
53 }
54}
55
56pub trait DntKeyProvider: Send + Sync {
58 fn resolve_key(&self, key_id: &KeyId, context: &DntContext) -> Result<SecretKey, DntKeyError>;
60}
61
62#[derive(Clone, Default)]
64pub struct StaticDntKeyProvider {
65 keys: HashMap<KeyId, SecretKey>,
66}
67
68impl fmt::Debug for StaticDntKeyProvider {
69 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
70 formatter
71 .debug_struct("StaticDntKeyProvider")
72 .field("keys", &self.keys.len())
73 .finish()
74 }
75}
76
77impl StaticDntKeyProvider {
78 pub fn new() -> Self {
80 Self::default()
81 }
82
83 pub fn with_key(mut self, key_id: KeyId, key: SecretKey) -> Self {
85 self.keys.insert(key_id, key);
86 self
87 }
88
89 pub fn insert(&mut self, key_id: KeyId, key: SecretKey) -> DntResult<()> {
91 self.keys.insert(key_id, key);
92 Ok(())
93 }
94}
95
96impl DntKeyProvider for StaticDntKeyProvider {
97 fn resolve_key(&self, key_id: &KeyId, _context: &DntContext) -> Result<SecretKey, DntKeyError> {
98 self.keys.get(key_id).cloned().ok_or(DntKeyError::NotFound)
99 }
100}