You can do this with the base64, aes, and cbc crates.
/*
[dependencies]
aes = "0.8.2"
base64 = "0.13.1"
cbc = { version = "0.1.2", features = ["alloc"] }
*/
use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyIvInit};
use std::str;
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
fn main() {
let key = [
142, 46, 73, 7, 14, 216, 229, 77, 195, 183, 29, 93, 159, 38, 53, 163,
];
let ciphertext = "tCmGLnG7+tKGSFBhtkn+sg==";
let ciphertext = base64::decode(&ciphertext).unwrap();
let decryptor = Aes128CbcDec::new(&key.into(), &[0; 16].into());
let plaintext = decryptor
.decrypt_padded_vec_mut::<Pkcs7>(&ciphertext)
.unwrap();
let plaintext = str::from_utf8(&plaintext).unwrap();
println!("{plaintext}");
}
Note that the base64 crate will not accept any whitespace in the Base64-encoded string: you'll have to filter out any whitespace before passing it into base64::decode(). Otherwise, it should be roughly equivalent to your Node.js snippet. You mention that you don't want large libraries, but it can't get much smaller than these three: they add 1.5 MB to a debug build, 33 kB to a release build, or 23 kB to a release build with LTO.