mochi_rs/imports/
crypto.rs

1extern crate alloc;
2
3use alloc::{string::String, vec::Vec};
4
5use super::core::PtrRef;
6
7#[link(wasm_import_module = "crypto")]
8// #[link(name = "swift-bindings", kind = "static")]
9extern "C" {
10    fn crypto_get_data_len(host_ptr: i32) -> i32;
11    fn crypto_get_data(host_ptr: i32, buf_ptr: i32, buf_len: i32);
12
13    fn crypto_base64_parse(
14        value_ptr: i32,
15        value_len: i32
16    ) -> i32;
17
18    fn crypto_base64_string(
19        bytes_ptr: i32,
20        bytes_len: i32
21    ) -> i32;
22
23    fn crypto_utf8_parse(
24        value_ptr: i32, 
25        value_len: i32
26    ) -> i32;
27
28    fn crypto_pbkdf2(
29        hash_algorithm: i32,
30        password_ptr: i32,
31        password_len: i32,
32        salt_ptr: i32,
33        salt_len: i32,
34        rounds: i32,
35        key_len: i32
36    ) -> i32;
37
38    fn crypto_generate_random_bytes(count: i32) -> i32;
39
40    fn crypto_aes_encrypt(
41        msg_ptr: i32,
42        msg_len: i32,
43        key_ptr: i32,
44        key_len: i32,
45        iv_ptr: i32,
46        iv_len: i32
47    ) -> i32;
48
49    fn crypto_aes_decrypt(
50        encrypted_msg_ptr: i32,
51        encrypted_msg_len: i32,
52        key_ptr: i32,
53        key_len: i32,
54        iv_ptr: i32,
55        iv_len: i32
56    ) -> i32;
57
58    fn crypto_md5_hash(
59        input_ptr: i32,
60        input_len: i32
61    ) -> i32;
62}
63
64
65#[repr(C)]
66pub enum CryptoPBKDFAlgorithm {
67    HmacAlgSHA1 = 1,
68    HmacAlgSHA224 = 2,
69    HmacAlgSHA256 = 3,
70    HmacAlgSHA384 = 4,
71    HmacAlgSHA512 = 5
72}
73
74// This represents CryptoJS but uses Apple's CryptoKit and CommonCrypto to
75// compute cryptographies
76//
77// This uses the CBC to follow CryptoJS's default decryption.
78pub struct Crypto {}
79
80// Parsers
81impl Crypto {
82    pub fn utf8_parse(value: &str) -> String {
83        let host_data_ptr = unsafe {
84            crypto_utf8_parse(
85                value.as_ptr() as i32, 
86                value.len() as i32
87            )
88        };
89
90        String::from_utf8(data_to_vec(host_data_ptr)).unwrap_or_default()
91    }
92
93    pub fn base64_parse(value: &str) -> Vec<u8> {
94        let host_data_ptr = unsafe {
95            crypto_base64_parse(
96                value.as_ptr() as i32, 
97                value.len() as i32
98            )
99        };
100        data_to_vec(host_data_ptr)
101    }
102
103    pub fn base64_string(bytes: &[u8]) -> String {
104        let host_string_ptr = unsafe {
105            crypto_base64_string(
106                bytes.as_ptr() as i32, 
107                bytes.len() as i32
108            )
109        };
110        let ptr = PtrRef::new(host_string_ptr);
111        ptr.as_string().unwrap_or_default()
112    }
113}
114
115// AES
116impl Crypto {
117    pub fn aes_encrypt(
118        msg: &[u8], 
119        key: &[u8], 
120        iv: &[u8]
121    ) -> Vec<u8> {
122        let data_ptr = unsafe {
123            crypto_aes_encrypt(
124                msg.as_ptr() as i32, 
125                msg.len() as i32, 
126                key.as_ptr() as i32, 
127                key.len() as i32, 
128                iv.as_ptr() as i32, 
129                iv.len() as i32
130            )
131        };
132        data_to_vec(data_ptr)
133    }
134
135    pub fn aes_decrypt(
136        encrypted_msg: &[u8],
137        key: &[u8],
138        iv: &[u8]
139    ) -> Vec<u8> {
140        let data_ptr = unsafe {
141            crypto_aes_decrypt(
142                encrypted_msg.as_ptr() as i32, 
143                encrypted_msg.len() as i32, 
144                key.as_ptr() as i32, 
145                key.len() as i32, 
146                iv.as_ptr() as i32, 
147                iv.len() as i32
148            )
149        };
150        data_to_vec(data_ptr)
151    }
152}
153
154// MD5
155impl Crypto {
156    pub fn md5_hash(
157        input: &[u8]
158    ) -> Vec<u8> {
159        let host_ptr = unsafe {
160            crypto_md5_hash(
161                input.as_ptr() as i32, 
162                input.len() as i32
163            )
164        };
165        data_to_vec(host_ptr)
166    }
167}
168
169impl Crypto {
170    pub fn generate_pbkdf2(
171        hash_algorithm: CryptoPBKDFAlgorithm,
172        password: &str,
173        salt: &[u8],
174        rounds: i32,
175        key_len: i32
176    ) -> Vec<u8> {
177        let host_ptr = unsafe {
178            crypto_pbkdf2(
179                hash_algorithm as i32, 
180                password.as_ptr() as i32, 
181                password.len() as i32, 
182                salt.as_ptr() as i32, 
183                salt.len() as i32, 
184                rounds, 
185                key_len
186            )
187        };
188        data_to_vec(host_ptr)
189    }
190
191    pub fn generate_random_bytes(count: i32) -> Vec<u8> {
192        let host_ptr = unsafe {
193            crypto_generate_random_bytes(count)
194        };
195        data_to_vec(host_ptr)
196    }
197}
198
199fn data_to_vec(host_data_ptr: i32) -> Vec<u8> {
200    if host_data_ptr >= 0 {
201        let data_size = unsafe { crypto_get_data_len(host_data_ptr) };
202        let mut buf = Vec::with_capacity(data_size as usize);
203        unsafe {
204            crypto_get_data(
205                host_data_ptr, 
206                buf.as_mut_ptr() as i32, 
207                data_size
208            );
209            buf.set_len(data_size as usize);
210        }
211        buf
212    } else {
213        Vec::new()
214    }
215}