Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/IPC/WindServiceHandlers/Encryption/
Decrypt.rs

1//! `encryption:decrypt(value: string) -> string`
2//!
3//! Reverses `encryption:encrypt`: base64-decodes, splits the 12-byte nonce
4//! from the ciphertext+tag, decrypts with AES-256-GCM, and returns the
5//! original plaintext string. Returns an empty string on any failure so the
6//! workbench treats a corrupt blob as "no stored secret" rather than crashing.
7
8use base64::{Engine, engine::general_purpose::STANDARD as B64};
9use ring::aead::{AES_256_GCM, Aad, LessSafeKey, Nonce, UnboundKey};
10use serde_json::{Value, json};
11
12use crate::{IPC::WindServiceHandlers::Utilities::JsonValueHelpers::arg_string, dev_log};
13use super::Key::Fn as DeriveKey;
14
15pub async fn Fn(Arguments:Vec<Value>) -> Result<Value, String> {
16	let Ciphertext = arg_string(&Arguments, 0);
17
18	if Ciphertext.is_empty() {
19		return Ok(json!(""));
20	}
21
22	let Blob = match B64.decode(&Ciphertext) {
23		Ok(B) => B,
24
25		Err(_) => {
26			dev_log!("encryption", "warn: encryption:decrypt invalid base64 - returning empty");
27
28			return Ok(json!(""));
29		},
30	};
31
32	// Minimum: 12 (nonce) + 16 (GCM tag) = 28 bytes
33	if Blob.len() < 28 {
34		dev_log!("encryption", "warn: encryption:decrypt blob too short ({} bytes)", Blob.len());
35
36		return Ok(json!(""));
37	}
38
39	let KeyBytes = DeriveKey().map_err(|E| format!("encryption:decrypt unavailable - {E}"))?;
40
41	let UnboundK = match UnboundKey::new(&AES_256_GCM, &KeyBytes) {
42		Ok(K) => K,
43
44		Err(_) => return Ok(json!("")),
45	};
46
47	let Key = LessSafeKey::new(UnboundK);
48
49	let NonceBytes:[u8; 12] = Blob[..12].try_into().unwrap();
50
51	let NonceVal = Nonce::assume_unique_for_key(NonceBytes);
52
53	let mut Data = Blob[12..].to_vec();
54
55	match Key.open_in_place(NonceVal, Aad::empty(), &mut Data) {
56		Ok(Plaintext) => {
57			let S = String::from_utf8_lossy(Plaintext).into_owned();
58
59			dev_log!("encryption", "encryption:decrypt ok ({} bytes)", S.len());
60
61			Ok(json!(S))
62		},
63
64		Err(_) => {
65			dev_log!(
66				"encryption",
67				"warn: encryption:decrypt open_in_place failed (wrong key or corrupt)"
68			);
69
70			Ok(json!(""))
71		},
72	}
73}