bsv_wasm/ecies/
ecies_ciphertext.rs

1use crate::{CipherKeys, PublicKey};
2#[cfg(target_arch = "wasm32")]
3use wasm_bindgen::{prelude::*, throw_str};
4
5use crate::BSVErrors;
6
7#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen)]
8pub struct ECIESCiphertext {
9    pub(crate) public_key_bytes: Option<Vec<u8>>,
10    pub(crate) ciphertext_bytes: Vec<u8>,
11    pub(crate) hmac_bytes: Vec<u8>,
12    pub(crate) keys: Option<CipherKeys>,
13}
14
15const PUB_KEY_OFFSET: u8 = 4;
16const PUB_KEY_END: u8 = PUB_KEY_OFFSET + 33;
17
18impl ECIESCiphertext {
19    pub(crate) fn extract_public_key_impl(&self) -> Result<PublicKey, BSVErrors> {
20        let bytes = self.public_key_bytes.clone().ok_or_else(|| BSVErrors::ECIESError("No public key exists in this ciphertext".into()))?;
21        PublicKey::from_bytes_impl(&bytes)
22    }
23
24    pub(crate) fn from_bytes_impl(buffer: &[u8], has_pub_key: bool) -> Result<ECIESCiphertext, BSVErrors> {
25        let pub_key = match has_pub_key {
26            true => {
27                let pub_key_buf = &buffer[PUB_KEY_OFFSET as usize..PUB_KEY_END as usize];
28                PublicKey::from_bytes_impl(pub_key_buf)?;
29                Some(pub_key_buf.to_vec())
30            }
31            false => None,
32        };
33
34        let hmac = &buffer[buffer.len() - 32..buffer.len()];
35        let ciphertext = match has_pub_key {
36            true => &buffer[PUB_KEY_END as usize..buffer.len() - 32],
37            false => &buffer[4..buffer.len() - 32],
38        };
39
40        Ok(ECIESCiphertext {
41            public_key_bytes: pub_key,
42            hmac_bytes: hmac.into(),
43            ciphertext_bytes: ciphertext.into(),
44            keys: None,
45        })
46    }
47}
48
49#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen)]
50impl ECIESCiphertext {
51    #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen(js_name = getCiphertext))]
52    pub fn get_ciphertext(&self) -> Vec<u8> {
53        self.ciphertext_bytes.clone()
54    }
55
56    #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen(js_name = getHMAC))]
57    pub fn get_hmac(&self) -> Vec<u8> {
58        self.hmac_bytes.clone()
59    }
60
61    #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen(js_name = getCipherKeys))]
62    pub fn get_cipher_keys(&self) -> Option<CipherKeys> {
63        self.keys.clone()
64    }
65
66    #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen(js_name = toBytes))]
67    pub fn to_bytes(&self) -> Vec<u8> {
68        let mut buffer = vec![];
69        buffer.extend_from_slice(b"BIE1");
70        if let Some(bytes) = self.public_key_bytes.clone() {
71            buffer.extend_from_slice(&bytes);
72        }
73        buffer.extend_from_slice(&self.ciphertext_bytes);
74        buffer.extend_from_slice(&self.hmac_bytes);
75
76        buffer
77    }
78}
79
80#[cfg(target_arch = "wasm32")]
81#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen)]
82impl ECIESCiphertext {
83    #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen(js_name = extractPublicKey))]
84    pub fn extract_public_key(&self) -> Result<PublicKey, JsValue> {
85        self.extract_public_key_impl().map_err(|e| JsValue::from_str(&e.to_string()))
86    }
87
88    #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen-ecies"), wasm_bindgen(js_name = fromBytes))]
89    pub fn from_bytes(buffer: &[u8], has_pub_key: bool) -> Result<ECIESCiphertext, JsValue> {
90        ECIESCiphertext::from_bytes_impl(buffer, has_pub_key).map_err(|e| JsValue::from_str(&e.to_string()))
91    }
92}
93
94#[cfg(not(target_arch = "wasm32"))]
95impl ECIESCiphertext {
96    pub fn extract_public_key(&self) -> Result<PublicKey, BSVErrors> {
97        self.extract_public_key_impl()
98    }
99
100    pub fn from_bytes(buffer: &[u8], has_pub_key: bool) -> Result<ECIESCiphertext, BSVErrors> {
101        ECIESCiphertext::from_bytes_impl(buffer, has_pub_key)
102    }
103}