Skip to main content

magic_crypt/
lib.rs

1/*!
2# MagicCrypt
3
4MagicCrypt is a Java/PHP/NodeJS/Rust library to encrypt/decrypt strings, files, or data, using Data Encryption Standard(DES) or Advanced Encryption Standard(AES) algorithms. It supports CBC block cipher mode, PKCS7 padding and 64, 128, 192 or 256-bits key length.
5
6## Security Notice
7
8MagicCrypt uses an older encryption design and is not recommended for new projects.
9
10For new applications, please use a modern library that supports authenticated encryption. Authenticated encryption can protect encrypted data from both reading and unauthorized changes.
11
12## For Rust
13
14### Example
15
16```rust
17use magic_crypt::{new_magic_crypt, MagicCryptTrait};
18
19let mc = new_magic_crypt!("magickey", 256);
20
21let base64 = mc.encrypt_str_to_base64("http://magiclen.org");
22
23assert_eq!("DS/2U8royDnJDiNY2ps3f6ZoTbpZo8ZtUGYLGEjwLDQ=", base64);
24
25assert_eq!("http://magiclen.org", mc.decrypt_base64_to_string(&base64).unwrap());
26```
27
28## Change the Buffer Size
29
30The default buffer size for the `encrypt_reader_to_writer` method and the `decrypt_reader_to_writer` method is 4096 bytes. If you want to change that, you can use the `encrypt_reader_to_writer2` method or the `decrypt_reader_to_writer2` method, and define a length explicitly.
31
32For example, to change the buffer size to 256 bytes,
33
34```rust
35use std::io::Cursor;
36
37use base64::Engine;
38use magic_crypt::{new_magic_crypt, MagicCryptTrait};
39use magic_crypt::array::typenum::U256;
40
41let mc = new_magic_crypt!("magickey", 256);
42
43# #[cfg(feature = "std")] {
44let mut reader = Cursor::new("http://magiclen.org");
45let mut writer = Vec::new();
46
47mc.encrypt_reader_to_writer2::<U256>(&mut reader, &mut writer).unwrap();
48
49let base64 = base64::engine::general_purpose::STANDARD.encode(&writer);
50
51assert_eq!("DS/2U8royDnJDiNY2ps3f6ZoTbpZo8ZtUGYLGEjwLDQ=", base64);
52
53assert_eq!("http://magiclen.org", mc.decrypt_base64_to_string(&base64).unwrap());
54# }
55```
56
57## No Std
58
59Disable the default features to compile this crate without std.
60
61```toml
62[dependencies.magic-crypt]
63version = "*"
64default-features = false
65```
66
67## For Java
68
69Refer to <https://github.com/magiclen/MagicCrypt>.
70
71## For PHP
72
73Refer to <https://github.com/magiclen/MagicCrypt>.
74
75## For NodeJS
76
77Refer to <https://github.com/magiclen/node-magiccrypt>.
78*/
79
80#![cfg_attr(not(feature = "std"), no_std)]
81
82extern crate alloc;
83
84mod ciphers;
85mod errors;
86mod functions;
87mod macros;
88mod secure_bit;
89mod traits;
90
91use alloc::vec::Vec;
92#[cfg(feature = "std")]
93use std::io::{Read, Write};
94
95#[cfg(feature = "std")]
96use array::ArraySize;
97#[cfg(feature = "std")]
98use array::typenum::{IsGreaterOrEqual, PartialDiv, True, U16};
99pub use cbc::cipher::array;
100pub use ciphers::{
101    aes128::MagicCrypt128, aes192::MagicCrypt192, aes256::MagicCrypt256, des64::MagicCrypt64,
102};
103pub use errors::MagicCryptError;
104pub use secure_bit::SecureBit;
105pub use traits::MagicCryptTrait;
106
107#[derive(Debug, Clone)]
108enum MagicCryptCipher {
109    DES64(MagicCrypt64),
110    AES128(MagicCrypt128),
111    AES192(MagicCrypt192),
112    AES256(MagicCrypt256),
113}
114
115/// This struct can help you encrypt or decrypt data in a quick way.
116#[derive(Debug, Clone)]
117pub struct MagicCrypt {
118    cipher: MagicCryptCipher,
119}
120
121impl MagicCrypt {
122    /// Create a new `MagicCrypt` instance. You may want to use the `new_magic_crypt!` macro.
123    pub fn new<S: AsRef<[u8]>, V: AsRef<[u8]>>(
124        key: S,
125        bit: SecureBit,
126        iv: Option<V>,
127    ) -> MagicCrypt {
128        let cipher = match bit {
129            SecureBit::Bit64 => MagicCryptCipher::DES64(MagicCrypt64::new(key, iv)),
130            SecureBit::Bit128 => MagicCryptCipher::AES128(MagicCrypt128::new(key, iv)),
131            SecureBit::Bit192 => MagicCryptCipher::AES192(MagicCrypt192::new(key, iv)),
132            SecureBit::Bit256 => MagicCryptCipher::AES256(MagicCrypt256::new(key, iv)),
133        };
134
135        MagicCrypt {
136            cipher,
137        }
138    }
139}
140
141impl MagicCryptTrait for MagicCrypt {
142    #[inline]
143    fn new<S: AsRef<[u8]>, V: AsRef<[u8]>>(key: S, iv: Option<V>) -> MagicCrypt {
144        MagicCrypt::new(key, SecureBit::default(), iv)
145    }
146
147    #[inline]
148    fn encrypt_to_bytes<T: ?Sized + AsRef<[u8]>>(&self, data: &T) -> Vec<u8> {
149        match &self.cipher {
150            MagicCryptCipher::DES64(mc) => mc.encrypt_to_bytes(data),
151            MagicCryptCipher::AES128(mc) => mc.encrypt_to_bytes(data),
152            MagicCryptCipher::AES192(mc) => mc.encrypt_to_bytes(data),
153            MagicCryptCipher::AES256(mc) => mc.encrypt_to_bytes(data),
154        }
155    }
156
157    #[cfg(feature = "std")]
158    #[inline]
159    fn encrypt_reader_to_bytes(&self, reader: &mut dyn Read) -> Result<Vec<u8>, MagicCryptError> {
160        match &self.cipher {
161            MagicCryptCipher::DES64(mc) => mc.encrypt_reader_to_bytes(reader),
162            MagicCryptCipher::AES128(mc) => mc.encrypt_reader_to_bytes(reader),
163            MagicCryptCipher::AES192(mc) => mc.encrypt_reader_to_bytes(reader),
164            MagicCryptCipher::AES256(mc) => mc.encrypt_reader_to_bytes(reader),
165        }
166    }
167
168    #[cfg(feature = "std")]
169    #[inline]
170    fn encrypt_reader_to_writer2<
171        N: ArraySize + PartialDiv<U16> + IsGreaterOrEqual<U16, Output = True>,
172    >(
173        &self,
174        reader: &mut dyn Read,
175        writer: &mut dyn Write,
176    ) -> Result<(), MagicCryptError> {
177        match &self.cipher {
178            MagicCryptCipher::DES64(mc) => mc.encrypt_reader_to_writer2::<N>(reader, writer),
179            MagicCryptCipher::AES128(mc) => mc.encrypt_reader_to_writer2::<N>(reader, writer),
180            MagicCryptCipher::AES192(mc) => mc.encrypt_reader_to_writer2::<N>(reader, writer),
181            MagicCryptCipher::AES256(mc) => mc.encrypt_reader_to_writer2::<N>(reader, writer),
182        }
183    }
184
185    #[inline]
186    fn decrypt_bytes_to_bytes<T: ?Sized + AsRef<[u8]>>(
187        &self,
188        bytes: &T,
189    ) -> Result<Vec<u8>, MagicCryptError> {
190        match &self.cipher {
191            MagicCryptCipher::DES64(mc) => mc.decrypt_bytes_to_bytes(bytes),
192            MagicCryptCipher::AES128(mc) => mc.decrypt_bytes_to_bytes(bytes),
193            MagicCryptCipher::AES192(mc) => mc.decrypt_bytes_to_bytes(bytes),
194            MagicCryptCipher::AES256(mc) => mc.decrypt_bytes_to_bytes(bytes),
195        }
196    }
197
198    #[cfg(feature = "std")]
199    #[inline]
200    fn decrypt_reader_to_bytes(&self, reader: &mut dyn Read) -> Result<Vec<u8>, MagicCryptError> {
201        match &self.cipher {
202            MagicCryptCipher::DES64(mc) => mc.decrypt_reader_to_bytes(reader),
203            MagicCryptCipher::AES128(mc) => mc.decrypt_reader_to_bytes(reader),
204            MagicCryptCipher::AES192(mc) => mc.decrypt_reader_to_bytes(reader),
205            MagicCryptCipher::AES256(mc) => mc.decrypt_reader_to_bytes(reader),
206        }
207    }
208
209    #[cfg(feature = "std")]
210    #[inline]
211    fn decrypt_reader_to_writer2<
212        N: ArraySize + PartialDiv<U16> + IsGreaterOrEqual<U16, Output = True>,
213    >(
214        &self,
215        reader: &mut dyn Read,
216        writer: &mut dyn Write,
217    ) -> Result<(), MagicCryptError> {
218        match &self.cipher {
219            MagicCryptCipher::DES64(mc) => mc.decrypt_reader_to_writer2::<N>(reader, writer),
220            MagicCryptCipher::AES128(mc) => mc.decrypt_reader_to_writer2::<N>(reader, writer),
221            MagicCryptCipher::AES192(mc) => mc.decrypt_reader_to_writer2::<N>(reader, writer),
222            MagicCryptCipher::AES256(mc) => mc.decrypt_reader_to_writer2::<N>(reader, writer),
223        }
224    }
225}