bsv_wasm/encryption/
mod.rs

1use crate::BSVErrors;
2use aes::{
3    cipher::{NewCipher, StreamCipher, StreamCipherSeek},
4    Aes128, Aes128Ctr, Aes256, Aes256Ctr,
5};
6use block_modes::{block_padding::Pkcs7, BlockMode, Cbc};
7#[cfg(target_arch = "wasm32")]
8use wasm_bindgen::{prelude::*, throw_str};
9
10#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-encryption"), wasm_bindgen)]
11pub struct AES {}
12
13#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-encryption"), wasm_bindgen)]
14#[allow(non_camel_case_types)]
15#[derive(Debug, Clone, Copy)]
16pub enum AESAlgorithms {
17    AES128_CBC,
18    AES256_CBC,
19    AES128_CTR,
20    AES256_CTR,
21}
22
23impl AES {
24    pub fn encrypt_impl(key: &[u8], iv: &[u8], message: &[u8], algo: AESAlgorithms) -> Result<Vec<u8>, BSVErrors> {
25        let result = match algo {
26            AESAlgorithms::AES128_CBC => Cbc::<Aes128, Pkcs7>::new_from_slices(key, iv)?.encrypt_vec(message),
27            AESAlgorithms::AES256_CBC => Cbc::<Aes256, Pkcs7>::new_from_slices(key, iv)?.encrypt_vec(message),
28            AESAlgorithms::AES128_CTR => AES::aes_ctr::<Aes128Ctr>(key, iv, message),
29            AESAlgorithms::AES256_CTR => AES::aes_ctr::<Aes256Ctr>(key, iv, message),
30        };
31
32        Ok(result)
33    }
34
35    pub fn decrypt_impl(key: &[u8], iv: &[u8], message: &[u8], algo: AESAlgorithms) -> Result<Vec<u8>, BSVErrors> {
36        let result = match algo {
37            AESAlgorithms::AES128_CBC => Cbc::<Aes128, Pkcs7>::new_from_slices(key, iv)?.decrypt_vec(message)?,
38            AESAlgorithms::AES256_CBC => Cbc::<Aes256, Pkcs7>::new_from_slices(key, iv)?.decrypt_vec(message)?,
39            AESAlgorithms::AES128_CTR => AES::aes_ctr::<Aes128Ctr>(key, iv, message),
40            AESAlgorithms::AES256_CTR => AES::aes_ctr::<Aes256Ctr>(key, iv, message),
41        };
42        Ok(result)
43    }
44
45    fn aes_ctr<T: NewCipher + StreamCipherSeek + StreamCipher>(key: &[u8], iv: &[u8], message: &[u8]) -> Vec<u8> {
46        let data = &mut message.to_vec();
47        let mut cipher = T::new(key.into(), iv.into());
48        cipher.seek(0);
49        cipher.apply_keystream(data);
50        data.to_vec()
51    }
52}
53
54#[cfg(target_arch = "wasm32")]
55#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-encryption"), wasm_bindgen)]
56impl AES {
57    #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-encryption"), wasm_bindgen(js_name = encrypt))]
58    pub fn encrypt(key: &[u8], iv: &[u8], message: &[u8], algo: AESAlgorithms) -> Result<Vec<u8>, JsValue> {
59        match AES::encrypt_impl(key, iv, message, algo) {
60            Ok(v) => Ok(v),
61            Err(e) => Err(JsValue::from_str(&e.to_string())),
62        }
63    }
64
65    #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-encryption"), wasm_bindgen(js_name = decrypt))]
66    pub fn decrypt(key: &[u8], iv: &[u8], message: &[u8], algo: AESAlgorithms) -> Result<Vec<u8>, JsValue> {
67        match AES::decrypt_impl(key, iv, message, algo) {
68            Ok(v) => Ok(v),
69            Err(e) => Err(JsValue::from_str(&e.to_string())),
70        }
71    }
72}
73
74#[cfg(not(target_arch = "wasm32"))]
75impl AES {
76    pub fn encrypt(key: &[u8], iv: &[u8], message: &[u8], algo: AESAlgorithms) -> Result<Vec<u8>, BSVErrors> {
77        AES::encrypt_impl(key, iv, message, algo)
78    }
79
80    pub fn decrypt(key: &[u8], iv: &[u8], message: &[u8], algo: AESAlgorithms) -> Result<Vec<u8>, BSVErrors> {
81        AES::decrypt_impl(key, iv, message, algo)
82    }
83}