wasmium_securemem/
prekey_vault.rs1mod prekey_vault {
2 use crate::{EncryptedVault, ProtectedEd25519KeyPair, SecureMemVault};
3 use chacha20poly1305::{
4 aead::{Aead, NewAead},
5 Key, XChaCha8Poly1305, XNonce,
6 };
7 use ed25519_dalek::Signature;
8 use nanorand::{ChaCha8, Rng};
9 use secrecy::{ExposeSecret, Secret};
10 use wasmium_errors::{WasmiumError, WasmiumResult};
11 use wasmium_random::WasmiumRandom;
12 use zeroize::Zeroize;
13
14 const VAULT_PAGES: usize = 4;
15 const EACH_VAULT_PAGE_SIZE: usize = 4096_usize;
16
17 lazy_static::lazy_static! {
18 static ref PREKEY: [[u8; EACH_VAULT_PAGE_SIZE]; VAULT_PAGES] = {
19 let mut pages = [[0_u8; EACH_VAULT_PAGE_SIZE]; VAULT_PAGES];
20
21 (0..VAULT_PAGES).for_each(|vault_page_index| {
22 let mut chacha_rng = ChaCha8::new();
23 let mut random_bytes = [0; EACH_VAULT_PAGE_SIZE];
24 (0..EACH_VAULT_PAGE_SIZE).for_each(|index| {
25 random_bytes[index] = chacha_rng.generate::<u8>();
26 });
27
28 pages[vault_page_index] = random_bytes;
29 });
30
31 pages
32 };
33 }
34
35 impl EncryptedVault {
36 fn sealing_key() -> Secret<SecureMemVault> {
37 let mut blake3_hasher = blake3::Hasher::new();
38 PREKEY.into_iter().for_each(|page| {
39 blake3_hasher.update(&page);
40 });
41
42 SecureMemVault::new(blake3_hasher.finalize())
43 }
44
45 pub fn encrypt_secret(
46 user_secrets: &mut ProtectedEd25519KeyPair,
47 ) -> WasmiumResult<EncryptedVault> {
48 let sealing_key = EncryptedVault::sealing_key();
49 let key = Key::from_slice(sealing_key.expose_secret().0.as_bytes()); let aead = XChaCha8Poly1305::new(key);
51
52 let random_nonce = Secret::new(WasmiumRandom::secure_alphanumeric24()); let nonce = XNonce::from_slice(random_nonce.expose_secret()); let ciphertext = match aead.encrypt(nonce, &user_secrets.0.to_bytes()[..]) {
55 Ok(ciphertext) => Secret::new(ciphertext),
56 Err(_) => return Err(WasmiumError::XChaCha8Poly1305EncryptionError),
57 };
58
59 user_secrets.zeroize();
60
61 Ok(EncryptedVault {
62 secret: ciphertext,
63 nonce: random_nonce,
64 })
65 }
66
67 pub fn decrypt_and_sign(&self, message: &[u8]) -> WasmiumResult<Signature> {
68 let sealing_key = EncryptedVault::sealing_key();
69 let key = Key::from_slice(sealing_key.expose_secret().0.as_bytes()); let aead = XChaCha8Poly1305::new(key);
71
72 let nonce = XNonce::from_slice(self.nonce.expose_secret()); let plaintext = match aead.decrypt(nonce, self.secret.expose_secret().as_ref()) {
74 Ok(plaintext) => Secret::new(plaintext),
75 Err(_) => return Err(WasmiumError::XChaCha8Poly1305EncryptionError),
76 };
77
78 let keypair = ProtectedEd25519KeyPair::from_bytes(&plaintext.expose_secret())?;
79
80 keypair.try_sign(message)
81 }
82 }
83}