1use crate::{CryptoError, CryptoResult, KEY_SIZE};
4use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
5use ed25519_dalek::{SigningKey, VerifyingKey};
6use rand::rngs::OsRng;
7use serde::{Deserialize, Serialize};
8use zeroize::{Zeroize, ZeroizeOnDrop};
9
10#[derive(Clone, Zeroize, ZeroizeOnDrop)]
12pub struct MasterKey {
13 key: [u8; KEY_SIZE],
14}
15
16impl MasterKey {
17 pub fn derive_from_password(password: &str, salt: &[u8]) -> CryptoResult<Self> {
21 let argon2 = Argon2::default();
22
23 let salt_string = SaltString::encode_b64(salt)
25 .map_err(|e| CryptoError::KeyDerivation(e.to_string()))?;
26
27 let hash = argon2
28 .hash_password(password.as_bytes(), &salt_string)
29 .map_err(|e| CryptoError::KeyDerivation(e.to_string()))?;
30
31 let hash_bytes = hash.hash.ok_or_else(|| {
32 CryptoError::KeyDerivation("No hash output".to_string())
33 })?;
34
35 let mut key = [0u8; KEY_SIZE];
36 key.copy_from_slice(&hash_bytes.as_bytes()[..KEY_SIZE]);
37
38 Ok(Self { key })
39 }
40
41 pub fn generate() -> CryptoResult<Self> {
43 let mut key = [0u8; KEY_SIZE];
44 rand::RngCore::fill_bytes(&mut OsRng, &mut key);
45 Ok(Self { key })
46 }
47
48 pub fn as_bytes(&self) -> &[u8; KEY_SIZE] {
50 &self.key
51 }
52
53 pub fn generate_salt() -> [u8; 16] {
55 let mut salt = [0u8; 16];
56 rand::RngCore::fill_bytes(&mut OsRng, &mut salt);
57 salt
58 }
59}
60
61#[derive(Clone, Zeroize, ZeroizeOnDrop)]
63pub struct DerivedKeys {
64 pub kek: [u8; KEY_SIZE],
66 pub auth_key: [u8; KEY_SIZE],
68}
69
70impl DerivedKeys {
71 pub fn derive_from_master(master: &MasterKey) -> Self {
73 let kek = *blake3::keyed_hash(master.as_bytes(), b"firecloud-kek-v1").as_bytes();
75 let auth_key = *blake3::keyed_hash(master.as_bytes(), b"firecloud-auth-v1").as_bytes();
76
77 Self { kek, auth_key }
78 }
79}
80
81#[derive(Clone)]
83pub struct KeyPair {
84 signing_key: SigningKey,
85}
86
87impl KeyPair {
88 pub fn generate() -> Self {
90 let signing_key = SigningKey::generate(&mut OsRng);
91 Self { signing_key }
92 }
93
94 pub fn from_seed(seed: &[u8; 32]) -> Self {
96 let signing_key = SigningKey::from_bytes(seed);
97 Self { signing_key }
98 }
99
100 pub fn public_key(&self) -> VerifyingKey {
102 self.signing_key.verifying_key()
103 }
104
105 pub fn public_key_bytes(&self) -> [u8; 32] {
107 self.public_key().to_bytes()
108 }
109
110 pub fn sign(&self, message: &[u8]) -> [u8; 64] {
112 use ed25519_dalek::Signer;
113 self.signing_key.sign(message).to_bytes()
114 }
115
116 pub fn verify(&self, message: &[u8], signature: &[u8; 64]) -> CryptoResult<()> {
118 use ed25519_dalek::{Signature, Verifier};
119 let sig = Signature::from_bytes(signature);
120 self.public_key()
121 .verify(message, &sig)
122 .map_err(|_| CryptoError::SignatureVerification)
123 }
124
125 pub fn to_bytes(&self) -> [u8; 32] {
127 self.signing_key.to_bytes()
128 }
129
130 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
132 Self {
133 signing_key: SigningKey::from_bytes(bytes),
134 }
135 }
136}
137
138pub fn generate_dek() -> [u8; KEY_SIZE] {
140 let mut dek = [0u8; KEY_SIZE];
141 rand::RngCore::fill_bytes(&mut OsRng, &mut dek);
142 dek
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct EncryptedDek {
148 pub ciphertext: Vec<u8>,
150 pub nonce: [u8; 24],
152}